@blocknote/core 0.8.5 → 0.9.2
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.js +705 -572
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +5 -4
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/BlockNoteEditor.ts +13 -17
- package/src/BlockNoteExtensions.ts +42 -27
- package/src/api/blockManipulation/blockManipulation.test.ts +2 -2
- package/src/api/blockManipulation/blockManipulation.ts +1 -1
- package/src/api/formatConversions/formatConversions.test.ts +2 -2
- package/src/api/formatConversions/formatConversions.ts +47 -3
- package/src/api/nodeConversions/nodeConversions.test.ts +6 -6
- package/src/api/nodeConversions/nodeConversions.ts +6 -6
- package/src/editor.module.css +0 -11
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +2 -2
- package/src/extensions/Blocks/api/block.ts +55 -22
- package/src/extensions/Blocks/api/blockTypes.ts +22 -3
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +27 -5
- package/src/extensions/Blocks/index.ts +7 -12
- package/src/extensions/Blocks/nodes/Block.module.css +1 -1
- package/src/extensions/Blocks/nodes/BlockContainer.ts +20 -19
- package/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts +20 -2
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +20 -2
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +20 -2
- package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +29 -6
- package/src/extensions/Blocks/nodes/BlockGroup.ts +19 -11
- package/src/extensions/SideMenu/MultipleNodeSelection.ts +3 -3
- package/src/extensions/SideMenu/SideMenuPlugin.ts +9 -9
- package/src/extensions/UniqueID/UniqueID.ts +10 -9
- package/src/index.ts +1 -0
- package/src/shared/EventEmitter.ts +1 -0
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +6 -2
- package/src/shared/utils.ts +4 -0
- package/types/src/BlockNoteEditor.d.ts +4 -10
- package/types/src/BlockNoteExtensions.d.ts +2 -0
- package/types/src/extensions/Blocks/api/block.d.ts +6 -1
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +15 -3
- package/types/src/extensions/Blocks/api/defaultBlocks.d.ts +36 -4
- package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +9 -1
- package/types/src/extensions/Blocks/index.d.ts +4 -1
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +9 -4
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +9 -1
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +9 -1
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +9 -1
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +9 -1
- package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +9 -1
- package/types/src/extensions/Blocks/nodes/TableCell.d.ts +5 -0
- package/types/src/extensions/Blocks/nodes/TableRow.d.ts +5 -0
- package/types/src/extensions/SideMenu/MultipleNodeSelection.d.ts +1 -1
- package/types/src/index.d.ts +1 -0
- package/types/src/shared/utils.d.ts +1 -0
- package/src/node_modules/.vitest/results.json +0 -1
- package/types/src/EventEmitter.d.ts +0 -11
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +0 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +0 -16
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +0 -55
- package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +0 -24
- package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +0 -11
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +0 -10
- package/types/src/extensions/HyperlinkToolbar/HyperlinkMark.d.ts +0 -8
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +0 -0
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +0 -13
- package/types/src/extensions/SlashMenu/index.d.ts +0 -3
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +0 -12
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
import { Node, NodeType } from "prosemirror-model";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type BlockInfoWithoutPositions = {
|
|
4
4
|
id: string;
|
|
5
5
|
node: Node;
|
|
6
6
|
contentNode: Node;
|
|
7
7
|
contentType: NodeType;
|
|
8
8
|
numChildBlocks: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type BlockInfo = BlockInfoWithoutPositions & {
|
|
9
12
|
startPos: number;
|
|
10
13
|
endPos: number;
|
|
11
14
|
depth: number;
|
|
12
15
|
};
|
|
13
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Helper function for `getBlockInfoFromPos`, returns information regarding
|
|
19
|
+
* provided blockContainer node.
|
|
20
|
+
* @param blockContainer The blockContainer node to retrieve info for.
|
|
21
|
+
*/
|
|
22
|
+
export function getBlockInfo(blockContainer: Node): BlockInfoWithoutPositions {
|
|
23
|
+
const id = blockContainer.attrs["id"];
|
|
24
|
+
const contentNode = blockContainer.firstChild!;
|
|
25
|
+
const contentType = contentNode.type;
|
|
26
|
+
const numChildBlocks =
|
|
27
|
+
blockContainer.childCount === 2 ? blockContainer.lastChild!.childCount : 0;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
id,
|
|
31
|
+
node: blockContainer,
|
|
32
|
+
contentNode,
|
|
33
|
+
contentType,
|
|
34
|
+
numChildBlocks,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
14
38
|
/**
|
|
15
39
|
* Retrieves information regarding the nearest blockContainer node in a
|
|
16
40
|
* ProseMirror doc, relative to a position.
|
|
@@ -56,6 +80,7 @@ export function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {
|
|
|
56
80
|
let node = $pos.node(maxDepth);
|
|
57
81
|
let depth = maxDepth;
|
|
58
82
|
|
|
83
|
+
// eslint-disable-next-line no-constant-condition
|
|
59
84
|
while (true) {
|
|
60
85
|
if (depth < 0) {
|
|
61
86
|
throw new Error(
|
|
@@ -71,10 +96,7 @@ export function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {
|
|
|
71
96
|
node = $pos.node(depth);
|
|
72
97
|
}
|
|
73
98
|
|
|
74
|
-
const id = node
|
|
75
|
-
const contentNode = node.firstChild!;
|
|
76
|
-
const contentType = contentNode.type;
|
|
77
|
-
const numChildBlocks = node.childCount === 2 ? node.lastChild!.childCount : 0;
|
|
99
|
+
const { id, contentNode, contentType, numChildBlocks } = getBlockInfo(node);
|
|
78
100
|
|
|
79
101
|
const startPos = $pos.start(depth);
|
|
80
102
|
const endPos = $pos.end(depth);
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { Node } from "@tiptap/core";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
name: "doc",
|
|
10
|
-
topNode: true,
|
|
11
|
-
content: "blockGroup",
|
|
12
|
-
}),
|
|
13
|
-
];
|
|
2
|
+
export { BlockContainer } from "./nodes/BlockContainer";
|
|
3
|
+
export { BlockGroup } from "./nodes/BlockGroup";
|
|
4
|
+
export const Doc = Node.create({
|
|
5
|
+
name: "doc",
|
|
6
|
+
topNode: true,
|
|
7
|
+
content: "blockGroup",
|
|
8
|
+
});
|
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
inlineContentToNodes,
|
|
7
7
|
} from "../../../api/nodeConversions/nodeConversions";
|
|
8
8
|
|
|
9
|
+
import {
|
|
10
|
+
BlockNoteDOMAttributes,
|
|
11
|
+
BlockSchema,
|
|
12
|
+
PartialBlock,
|
|
13
|
+
} from "../api/blockTypes";
|
|
9
14
|
import { getBlockInfoFromPos } from "../helpers/getBlockInfoFromPos";
|
|
10
15
|
import { PreviousBlockTypePlugin } from "../PreviousBlockTypePlugin";
|
|
11
16
|
import styles from "./Block.module.css";
|
|
12
17
|
import BlockAttributes from "./BlockAttributes";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
// TODO
|
|
16
|
-
export interface IBlock {
|
|
17
|
-
HTMLAttributes: Record<string, any>;
|
|
18
|
-
}
|
|
18
|
+
import { mergeCSSClasses } from "../../../shared/utils";
|
|
19
19
|
|
|
20
20
|
declare module "@tiptap/core" {
|
|
21
21
|
interface Commands<ReturnType> {
|
|
@@ -39,7 +39,9 @@ declare module "@tiptap/core" {
|
|
|
39
39
|
/**
|
|
40
40
|
* The main "Block node" documents consist of
|
|
41
41
|
*/
|
|
42
|
-
export const BlockContainer = Node.create<
|
|
42
|
+
export const BlockContainer = Node.create<{
|
|
43
|
+
domAttributes?: BlockNoteDOMAttributes;
|
|
44
|
+
}>({
|
|
43
45
|
name: "blockContainer",
|
|
44
46
|
group: "blockContainer",
|
|
45
47
|
// A block always contains content, and optionally a blockGroup which contains nested blocks
|
|
@@ -48,12 +50,6 @@ export const BlockContainer = Node.create<IBlock>({
|
|
|
48
50
|
priority: 50,
|
|
49
51
|
defining: true,
|
|
50
52
|
|
|
51
|
-
addOptions() {
|
|
52
|
-
return {
|
|
53
|
-
HTMLAttributes: {},
|
|
54
|
-
};
|
|
55
|
-
},
|
|
56
|
-
|
|
57
53
|
parseHTML() {
|
|
58
54
|
return [
|
|
59
55
|
{
|
|
@@ -64,7 +60,7 @@ export const BlockContainer = Node.create<IBlock>({
|
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
const attrs: Record<string, string> = {};
|
|
67
|
-
for (
|
|
63
|
+
for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {
|
|
68
64
|
if (element.getAttribute(HTMLAttr)) {
|
|
69
65
|
attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;
|
|
70
66
|
}
|
|
@@ -81,6 +77,8 @@ export const BlockContainer = Node.create<IBlock>({
|
|
|
81
77
|
},
|
|
82
78
|
|
|
83
79
|
renderHTML({ HTMLAttributes }) {
|
|
80
|
+
const domAttributes = this.options.domAttributes?.blockContainer || {};
|
|
81
|
+
|
|
84
82
|
return [
|
|
85
83
|
"div",
|
|
86
84
|
mergeAttributes(HTMLAttributes, {
|
|
@@ -89,11 +87,14 @@ export const BlockContainer = Node.create<IBlock>({
|
|
|
89
87
|
}),
|
|
90
88
|
[
|
|
91
89
|
"div",
|
|
92
|
-
mergeAttributes(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
mergeAttributes(
|
|
91
|
+
{
|
|
92
|
+
...domAttributes,
|
|
93
|
+
class: mergeCSSClasses(styles.block, domAttributes.class),
|
|
94
|
+
"data-node-type": this.name,
|
|
95
|
+
},
|
|
96
|
+
HTMLAttributes
|
|
97
|
+
),
|
|
97
98
|
0,
|
|
98
99
|
],
|
|
99
100
|
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InputRule, mergeAttributes } from "@tiptap/core";
|
|
2
2
|
import { createTipTapBlock } from "../../../api/block";
|
|
3
3
|
import styles from "../../Block.module.css";
|
|
4
|
+
import { mergeCSSClasses } from "../../../../../shared/utils";
|
|
4
5
|
|
|
5
6
|
export const HeadingBlockContent = createTipTapBlock<"heading">({
|
|
6
7
|
name: "heading",
|
|
@@ -64,13 +65,30 @@ export const HeadingBlockContent = createTipTapBlock<"heading">({
|
|
|
64
65
|
},
|
|
65
66
|
|
|
66
67
|
renderHTML({ node, HTMLAttributes }) {
|
|
68
|
+
const blockContentDOMAttributes =
|
|
69
|
+
this.options.domAttributes?.blockContent || {};
|
|
70
|
+
const inlineContentDOMAttributes =
|
|
71
|
+
this.options.domAttributes?.inlineContent || {};
|
|
72
|
+
|
|
67
73
|
return [
|
|
68
74
|
"div",
|
|
69
75
|
mergeAttributes(HTMLAttributes, {
|
|
70
|
-
class:
|
|
76
|
+
class: mergeCSSClasses(
|
|
77
|
+
styles.blockContent,
|
|
78
|
+
blockContentDOMAttributes.class
|
|
79
|
+
),
|
|
71
80
|
"data-content-type": this.name,
|
|
72
81
|
}),
|
|
73
|
-
[
|
|
82
|
+
[
|
|
83
|
+
"h" + node.attrs.level,
|
|
84
|
+
{
|
|
85
|
+
class: mergeCSSClasses(
|
|
86
|
+
styles.inlineContent,
|
|
87
|
+
inlineContentDOMAttributes.class
|
|
88
|
+
),
|
|
89
|
+
},
|
|
90
|
+
0,
|
|
91
|
+
],
|
|
74
92
|
];
|
|
75
93
|
},
|
|
76
94
|
});
|
|
@@ -2,6 +2,7 @@ import { InputRule, mergeAttributes } from "@tiptap/core";
|
|
|
2
2
|
import { createTipTapBlock } from "../../../../api/block";
|
|
3
3
|
import { handleEnter } from "../ListItemKeyboardShortcuts";
|
|
4
4
|
import styles from "../../../Block.module.css";
|
|
5
|
+
import { mergeCSSClasses } from "../../../../../../shared/utils";
|
|
5
6
|
|
|
6
7
|
export const BulletListItemBlockContent = createTipTapBlock<"bulletListItem">({
|
|
7
8
|
name: "bulletListItem",
|
|
@@ -82,13 +83,30 @@ export const BulletListItemBlockContent = createTipTapBlock<"bulletListItem">({
|
|
|
82
83
|
},
|
|
83
84
|
|
|
84
85
|
renderHTML({ HTMLAttributes }) {
|
|
86
|
+
const blockContentDOMAttributes =
|
|
87
|
+
this.options.domAttributes?.blockContent || {};
|
|
88
|
+
const inlineContentDOMAttributes =
|
|
89
|
+
this.options.domAttributes?.inlineContent || {};
|
|
90
|
+
|
|
85
91
|
return [
|
|
86
92
|
"div",
|
|
87
93
|
mergeAttributes(HTMLAttributes, {
|
|
88
|
-
class:
|
|
94
|
+
class: mergeCSSClasses(
|
|
95
|
+
styles.blockContent,
|
|
96
|
+
blockContentDOMAttributes.class
|
|
97
|
+
),
|
|
89
98
|
"data-content-type": this.name,
|
|
90
99
|
}),
|
|
91
|
-
[
|
|
100
|
+
[
|
|
101
|
+
"p",
|
|
102
|
+
{
|
|
103
|
+
class: mergeCSSClasses(
|
|
104
|
+
styles.inlineContent,
|
|
105
|
+
inlineContentDOMAttributes.class
|
|
106
|
+
),
|
|
107
|
+
},
|
|
108
|
+
0,
|
|
109
|
+
],
|
|
92
110
|
];
|
|
93
111
|
},
|
|
94
112
|
});
|
|
@@ -3,6 +3,7 @@ import { createTipTapBlock } from "../../../../api/block";
|
|
|
3
3
|
import { handleEnter } from "../ListItemKeyboardShortcuts";
|
|
4
4
|
import { NumberedListIndexingPlugin } from "./NumberedListIndexingPlugin";
|
|
5
5
|
import styles from "../../../Block.module.css";
|
|
6
|
+
import { mergeCSSClasses } from "../../../../../../shared/utils";
|
|
6
7
|
|
|
7
8
|
export const NumberedListItemBlockContent =
|
|
8
9
|
createTipTapBlock<"numberedListItem">({
|
|
@@ -106,15 +107,32 @@ export const NumberedListItemBlockContent =
|
|
|
106
107
|
},
|
|
107
108
|
|
|
108
109
|
renderHTML({ HTMLAttributes }) {
|
|
110
|
+
const blockContentDOMAttributes =
|
|
111
|
+
this.options.domAttributes?.blockContent || {};
|
|
112
|
+
const inlineContentDOMAttributes =
|
|
113
|
+
this.options.domAttributes?.inlineContent || {};
|
|
114
|
+
|
|
109
115
|
return [
|
|
110
116
|
"div",
|
|
111
117
|
mergeAttributes(HTMLAttributes, {
|
|
112
|
-
class:
|
|
118
|
+
class: mergeCSSClasses(
|
|
119
|
+
styles.blockContent,
|
|
120
|
+
blockContentDOMAttributes.class
|
|
121
|
+
),
|
|
113
122
|
"data-content-type": this.name,
|
|
114
123
|
}),
|
|
115
124
|
// we use a <p> tag, because for <li> tags we'd need to add a <ul> parent for around siblings to be semantically correct,
|
|
116
125
|
// which would be quite cumbersome
|
|
117
|
-
[
|
|
126
|
+
[
|
|
127
|
+
"p",
|
|
128
|
+
{
|
|
129
|
+
class: mergeCSSClasses(
|
|
130
|
+
styles.inlineContent,
|
|
131
|
+
inlineContentDOMAttributes.class
|
|
132
|
+
),
|
|
133
|
+
},
|
|
134
|
+
0,
|
|
135
|
+
],
|
|
118
136
|
];
|
|
119
137
|
},
|
|
120
138
|
});
|
package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { mergeAttributes } from "@tiptap/core";
|
|
2
2
|
import { createTipTapBlock } from "../../../api/block";
|
|
3
3
|
import styles from "../../Block.module.css";
|
|
4
|
+
import { mergeCSSClasses } from "../../../../../shared/utils";
|
|
4
5
|
|
|
5
|
-
export const ParagraphBlockContent = createTipTapBlock
|
|
6
|
+
export const ParagraphBlockContent = createTipTapBlock({
|
|
6
7
|
name: "paragraph",
|
|
7
8
|
content: "inline*",
|
|
8
9
|
|
|
@@ -17,13 +18,35 @@ export const ParagraphBlockContent = createTipTapBlock<"paragraph">({
|
|
|
17
18
|
},
|
|
18
19
|
|
|
19
20
|
renderHTML({ HTMLAttributes }) {
|
|
21
|
+
const blockContentDOMAttributes =
|
|
22
|
+
this.options.domAttributes?.blockContent || {};
|
|
23
|
+
const inlineContentDOMAttributes =
|
|
24
|
+
this.options.domAttributes?.inlineContent || {};
|
|
25
|
+
|
|
20
26
|
return [
|
|
21
27
|
"div",
|
|
22
|
-
mergeAttributes(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
mergeAttributes(
|
|
29
|
+
{
|
|
30
|
+
...blockContentDOMAttributes,
|
|
31
|
+
class: mergeCSSClasses(
|
|
32
|
+
styles.blockContent,
|
|
33
|
+
blockContentDOMAttributes.class
|
|
34
|
+
),
|
|
35
|
+
"data-content-type": this.name,
|
|
36
|
+
},
|
|
37
|
+
HTMLAttributes
|
|
38
|
+
),
|
|
39
|
+
[
|
|
40
|
+
"p",
|
|
41
|
+
{
|
|
42
|
+
...inlineContentDOMAttributes,
|
|
43
|
+
class: mergeCSSClasses(
|
|
44
|
+
styles.inlineContent,
|
|
45
|
+
inlineContentDOMAttributes.class
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
0,
|
|
49
|
+
],
|
|
27
50
|
];
|
|
28
51
|
},
|
|
29
52
|
});
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { mergeAttributes, Node } from "@tiptap/core";
|
|
2
2
|
import styles from "./Block.module.css";
|
|
3
|
+
import { BlockNoteDOMAttributes } from "../api/blockTypes";
|
|
4
|
+
import { mergeCSSClasses } from "../../../shared/utils";
|
|
3
5
|
|
|
4
|
-
export const BlockGroup = Node.create
|
|
6
|
+
export const BlockGroup = Node.create<{
|
|
7
|
+
domAttributes?: BlockNoteDOMAttributes;
|
|
8
|
+
}>({
|
|
5
9
|
name: "blockGroup",
|
|
6
10
|
group: "blockGroup",
|
|
7
11
|
content: "blockContainer+",
|
|
8
12
|
|
|
9
|
-
addOptions() {
|
|
10
|
-
return {
|
|
11
|
-
HTMLAttributes: {},
|
|
12
|
-
};
|
|
13
|
-
},
|
|
14
|
-
|
|
15
13
|
parseHTML() {
|
|
16
14
|
return [
|
|
17
15
|
{
|
|
@@ -33,12 +31,22 @@ export const BlockGroup = Node.create({
|
|
|
33
31
|
},
|
|
34
32
|
|
|
35
33
|
renderHTML({ HTMLAttributes }) {
|
|
34
|
+
const blockGroupDOMAttributes =
|
|
35
|
+
this.options.domAttributes?.blockGroup || {};
|
|
36
|
+
|
|
36
37
|
return [
|
|
37
38
|
"div",
|
|
38
|
-
mergeAttributes(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
mergeAttributes(
|
|
40
|
+
{
|
|
41
|
+
...blockGroupDOMAttributes,
|
|
42
|
+
class: mergeCSSClasses(
|
|
43
|
+
styles.blockGroup,
|
|
44
|
+
blockGroupDOMAttributes.class
|
|
45
|
+
),
|
|
46
|
+
"data-node-type": "blockGroup",
|
|
47
|
+
},
|
|
48
|
+
HTMLAttributes
|
|
49
|
+
),
|
|
42
50
|
0,
|
|
43
51
|
];
|
|
44
52
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Selection } from "prosemirror-state";
|
|
2
1
|
import { Fragment, Node, ResolvedPos, Slice } from "prosemirror-model";
|
|
2
|
+
import { Selection } from "prosemirror-state";
|
|
3
3
|
import { Mappable } from "prosemirror-transform";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -64,8 +64,8 @@ export class MultipleNodeSelection extends Selection {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
map(doc: Node, mapping: Mappable): Selection {
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const fromResult = mapping.mapResult(this.from);
|
|
68
|
+
const toResult = mapping.mapResult(this.to);
|
|
69
69
|
|
|
70
70
|
if (toResult.deleted) {
|
|
71
71
|
return Selection.near(doc.resolve(fromResult.pos));
|
|
@@ -32,7 +32,7 @@ function getDraggableBlockFromCoords(
|
|
|
32
32
|
return undefined;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const pos = view.posAtCoords(coords);
|
|
36
36
|
if (!pos) {
|
|
37
37
|
return undefined;
|
|
38
38
|
}
|
|
@@ -61,12 +61,12 @@ function blockPositionFromCoords(
|
|
|
61
61
|
coords: { left: number; top: number },
|
|
62
62
|
view: EditorView
|
|
63
63
|
) {
|
|
64
|
-
|
|
64
|
+
const block = getDraggableBlockFromCoords(coords, view);
|
|
65
65
|
|
|
66
66
|
if (block && block.node.nodeType === 1) {
|
|
67
67
|
// TODO: this uses undocumented PM APIs? do we need this / let's add docs?
|
|
68
68
|
const docView = (view as any).docView;
|
|
69
|
-
|
|
69
|
+
const desc = docView.nearestDesc(block.node, true);
|
|
70
70
|
if (!desc || desc === docView) {
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
@@ -186,12 +186,12 @@ function dragStart(
|
|
|
186
186
|
|
|
187
187
|
const editorBoundingBox = view.dom.getBoundingClientRect();
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
const coords = {
|
|
190
190
|
left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
|
|
191
191
|
top: e.clientY,
|
|
192
192
|
};
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
const pos = blockPositionFromCoords(coords, view);
|
|
195
195
|
if (pos != null) {
|
|
196
196
|
const selection = view.state.selection;
|
|
197
197
|
const doc = view.state.doc;
|
|
@@ -215,8 +215,8 @@ function dragStart(
|
|
|
215
215
|
setDragImage(view, pos);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
const slice = view.state.selection.content();
|
|
219
|
+
const { dom, text } = serializeForClipboard(view, slice);
|
|
220
220
|
|
|
221
221
|
e.dataTransfer.clearData();
|
|
222
222
|
e.dataTransfer.setData("text/html", dom.innerHTML);
|
|
@@ -288,7 +288,7 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
|
|
|
288
288
|
return;
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
|
|
291
|
+
const pos = this.pmView.posAtCoords({
|
|
292
292
|
left: event.clientX,
|
|
293
293
|
top: event.clientY,
|
|
294
294
|
});
|
|
@@ -319,7 +319,7 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
|
|
|
319
319
|
if ((event as any).synthetic || !this.isDragging) {
|
|
320
320
|
return;
|
|
321
321
|
}
|
|
322
|
-
|
|
322
|
+
const pos = this.pmView.posAtCoords({
|
|
323
323
|
left: event.clientX,
|
|
324
324
|
top: event.clientY,
|
|
325
325
|
});
|
|
@@ -52,14 +52,15 @@ const UniqueID = Extension.create({
|
|
|
52
52
|
types: [],
|
|
53
53
|
generateID: () => {
|
|
54
54
|
// Use mock ID if tests are running.
|
|
55
|
-
if ((window as any).__TEST_OPTIONS) {
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (typeof window !== "undefined" && (window as any).__TEST_OPTIONS) {
|
|
56
|
+
const testOptions = (window as any).__TEST_OPTIONS;
|
|
57
|
+
if (testOptions.mockID === undefined) {
|
|
58
|
+
testOptions.mockID = 0;
|
|
58
59
|
} else {
|
|
59
|
-
|
|
60
|
+
testOptions.mockID++;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
return
|
|
63
|
+
return testOptions.mockID.toString() as string;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
return v4();
|
|
@@ -129,7 +130,7 @@ const UniqueID = Extension.create({
|
|
|
129
130
|
const filterTransactions =
|
|
130
131
|
this.options.filterTransaction &&
|
|
131
132
|
transactions.some((tr) => {
|
|
132
|
-
|
|
133
|
+
let _a, _b;
|
|
133
134
|
return !((_b = (_a = this.options).filterTransaction) === null ||
|
|
134
135
|
_b === void 0
|
|
135
136
|
? void 0
|
|
@@ -161,7 +162,7 @@ const UniqueID = Extension.create({
|
|
|
161
162
|
.filter((id) => id !== null);
|
|
162
163
|
const duplicatedNewIds = findDuplicates(newIds);
|
|
163
164
|
newNodes.forEach(({ node, pos }) => {
|
|
164
|
-
|
|
165
|
+
let _a;
|
|
165
166
|
// instead of checking `node.attrs[attributeName]` directly
|
|
166
167
|
// we look at the current state of the node within `tr.doc`.
|
|
167
168
|
// this helps to prevent adding new ids to the same node
|
|
@@ -196,7 +197,7 @@ const UniqueID = Extension.create({
|
|
|
196
197
|
// we register a global drag handler to track the current drag source element
|
|
197
198
|
view(view) {
|
|
198
199
|
const handleDragstart = (event: any) => {
|
|
199
|
-
|
|
200
|
+
let _a;
|
|
200
201
|
dragSourceElement = (
|
|
201
202
|
(_a = view.dom.parentElement) === null || _a === void 0
|
|
202
203
|
? void 0
|
|
@@ -219,7 +220,7 @@ const UniqueID = Extension.create({
|
|
|
219
220
|
// only create new ids for dropped content while holding `alt`
|
|
220
221
|
// or content is dragged from another editor
|
|
221
222
|
drop: (view, event: any) => {
|
|
222
|
-
|
|
223
|
+
let _a;
|
|
223
224
|
if (
|
|
224
225
|
dragSourceElement !== view.dom.parentElement ||
|
|
225
226
|
((_a = event.dataTransfer) === null || _a === void 0
|
package/src/index.ts
CHANGED
|
@@ -15,3 +15,4 @@ export { getDefaultSlashMenuItems } from "./extensions/SlashMenu/defaultSlashMen
|
|
|
15
15
|
export * from "./shared/BaseUiElementTypes";
|
|
16
16
|
export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
|
|
17
17
|
export * from "./shared/plugins/suggestion/SuggestionPlugin";
|
|
18
|
+
export * from "./shared/utils";
|
|
@@ -11,6 +11,7 @@ type CallbackFunction<
|
|
|
11
11
|
> = (...props: CallbackType<T, EventName>) => any;
|
|
12
12
|
|
|
13
13
|
export class EventEmitter<T extends Record<string, any>> {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
14
15
|
private callbacks: { [key: string]: Function[] } = {};
|
|
15
16
|
|
|
16
17
|
public on<EventName extends StringKeyOf<T>>(
|
|
@@ -28,7 +28,9 @@ class SuggestionsMenuView<
|
|
|
28
28
|
private readonly pluginKey: PluginKey,
|
|
29
29
|
updateSuggestionsMenu: (
|
|
30
30
|
suggestionsMenuState: SuggestionsMenuState<T>
|
|
31
|
-
) => void = () => {
|
|
31
|
+
) => void = () => {
|
|
32
|
+
// noop
|
|
33
|
+
}
|
|
32
34
|
) {
|
|
33
35
|
this.pluginState = getDefaultPluginState<T>();
|
|
34
36
|
|
|
@@ -158,7 +160,9 @@ export const setupSuggestionsMenu = <
|
|
|
158
160
|
onSelectItem: (props: {
|
|
159
161
|
item: T;
|
|
160
162
|
editor: BlockNoteEditor<BSchema>;
|
|
161
|
-
}) => void = () => {
|
|
163
|
+
}) => void = () => {
|
|
164
|
+
// noop
|
|
165
|
+
}
|
|
162
166
|
) => {
|
|
163
167
|
// Assertions
|
|
164
168
|
if (defaultTriggerCharacter.length !== 1) {
|
package/src/shared/utils.ts
CHANGED
|
@@ -11,6 +11,10 @@ export function formatKeyboardShortcut(shortcut: string) {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export function mergeCSSClasses(...classes: string[]) {
|
|
15
|
+
return classes.filter((c) => c).join(" ");
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
export class UnreachableCaseError extends Error {
|
|
15
19
|
constructor(val: never) {
|
|
16
20
|
super(`Unreachable case: ${val}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Node } from "prosemirror-model";
|
|
2
2
|
import { Editor as TiptapEditor } from "@tiptap/core/dist/packages/core/src/Editor";
|
|
3
3
|
import * as Y from "yjs";
|
|
4
|
-
import { Block, BlockIdentifier, BlockSchema, PartialBlock } from "./extensions/Blocks/api/blockTypes";
|
|
4
|
+
import { Block, BlockIdentifier, BlockNoteDOMAttributes, BlockSchema, PartialBlock } from "./extensions/Blocks/api/blockTypes";
|
|
5
5
|
import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes";
|
|
6
6
|
import { DefaultBlockSchema } from "./extensions/Blocks/api/defaultBlocks";
|
|
7
7
|
import { Styles } from "./extensions/Blocks/api/inlineContentTypes";
|
|
@@ -27,11 +27,11 @@ export type BlockNoteEditorOptions<BSchema extends BlockSchema> = {
|
|
|
27
27
|
*/
|
|
28
28
|
parentElement: HTMLElement;
|
|
29
29
|
/**
|
|
30
|
-
* An object containing attributes that should be added to the editor
|
|
30
|
+
* An object containing attributes that should be added to HTML elements of the editor.
|
|
31
31
|
*
|
|
32
|
-
* @example { class: "my-editor-class" }
|
|
32
|
+
* @example { editor: { class: "my-editor-class" } }
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
domAttributes: Partial<BlockNoteDOMAttributes>;
|
|
35
35
|
/**
|
|
36
36
|
* A callback function that runs when the editor is ready to be used.
|
|
37
37
|
*/
|
|
@@ -58,12 +58,6 @@ export type BlockNoteEditorOptions<BSchema extends BlockSchema> = {
|
|
|
58
58
|
* @default true
|
|
59
59
|
*/
|
|
60
60
|
defaultStyles: boolean;
|
|
61
|
-
/**
|
|
62
|
-
* Whether to use the light or dark theme.
|
|
63
|
-
*
|
|
64
|
-
* @default "light"
|
|
65
|
-
*/
|
|
66
|
-
theme: "light" | "dark";
|
|
67
61
|
/**
|
|
68
62
|
* A list of block types that should be available in the editor.
|
|
69
63
|
*/
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Extensions } from "@tiptap/core";
|
|
2
2
|
import { BlockNoteEditor } from "./BlockNoteEditor";
|
|
3
3
|
import * as Y from "yjs";
|
|
4
|
+
import { BlockNoteDOMAttributes } from "./extensions/Blocks/api/blockTypes";
|
|
4
5
|
/**
|
|
5
6
|
* Get all the Tiptap extensions BlockNote is configured with by default
|
|
6
7
|
*/
|
|
7
8
|
export declare const getBlockNoteExtensions: <BSchema extends Record<string, import("./extensions/Blocks/api/blockTypes").BlockSpec<string, import("./extensions/Blocks/api/blockTypes").PropSchema>>>(opts: {
|
|
8
9
|
editor: BlockNoteEditor<BSchema>;
|
|
10
|
+
domAttributes: Partial<BlockNoteDOMAttributes>;
|
|
9
11
|
blockSchema: BSchema;
|
|
10
12
|
collaboration?: {
|
|
11
13
|
fragment: Y.XmlFragment;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Attribute } from "@tiptap/core";
|
|
2
|
+
import { BlockNoteDOMAttributes } from "../../..";
|
|
2
3
|
import { BlockConfig, BlockSchema, BlockSpec, PropSchema, TipTapNode, TipTapNodeConfig } from "./blockTypes";
|
|
3
4
|
export declare function camelToDataKebab(str: string): string;
|
|
4
5
|
export declare function propsToAttributes<BType extends string, PSchema extends PropSchema, ContainsInlineContent extends boolean, BSchema extends BlockSchema>(blockConfig: Omit<BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>, "render">): Record<string, Attribute>;
|
|
@@ -13,4 +14,8 @@ export declare function render<BType extends string, PSchema extends PropSchema,
|
|
|
13
14
|
contentDOM?: undefined;
|
|
14
15
|
};
|
|
15
16
|
export declare function createBlockSpec<BType extends string, PSchema extends PropSchema, ContainsInlineContent extends boolean, BSchema extends BlockSchema>(blockConfig: BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>): BlockSpec<BType, PSchema>;
|
|
16
|
-
export declare function createTipTapBlock<Type extends string
|
|
17
|
+
export declare function createTipTapBlock<Type extends string, Options extends {
|
|
18
|
+
domAttributes?: BlockNoteDOMAttributes;
|
|
19
|
+
} = {
|
|
20
|
+
domAttributes?: BlockNoteDOMAttributes;
|
|
21
|
+
}, Storage = any>(config: TipTapNodeConfig<Type, Options, Storage>): TipTapNode<Type, Options, Storage>;
|