@blocknote/core 0.2.2 → 0.2.4-alpha.7
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 +1061 -936
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +1 -1
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +22 -29
- package/src/BlockNoteExtensions.ts +11 -10
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +61 -0
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +62 -0
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +112 -106
- package/src/extensions/Blocks/apiTypes.ts +48 -0
- package/src/extensions/Blocks/helpers/findBlock.ts +3 -1
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +1 -1
- package/src/extensions/Blocks/index.ts +10 -8
- package/src/extensions/Blocks/nodes/Block.module.css +122 -35
- package/src/extensions/Blocks/{BlockAttributes.ts → nodes/BlockAttributes.ts} +0 -0
- package/src/extensions/Blocks/nodes/{Block.ts → BlockContainer.ts} +113 -119
- package/src/extensions/Blocks/nodes/{BlockTypes/HeadingBlock/HeadingContent.ts → BlockContent/HeadingBlockContent/HeadingBlockContent.ts} +16 -24
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +76 -0
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.ts +47 -0
- package/src/extensions/Blocks/nodes/{BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts → BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts} +10 -14
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +95 -0
- package/src/extensions/Blocks/nodes/{BlockTypes/TextBlock/TextContent.ts → BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts} +7 -12
- package/src/extensions/Blocks/nodes/BlockGroup.ts +4 -4
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +9 -1
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +87 -42
- package/src/extensions/{Blocks → DraggableBlocks}/MultipleNodeSelection.ts +0 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +20 -7
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +51 -12
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +1 -1
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +3 -1
- package/src/extensions/Placeholder/PlaceholderExtension.ts +1 -1
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +1 -1
- package/src/extensions/SlashMenu/SlashMenuItem.ts +3 -28
- package/src/extensions/SlashMenu/defaultCommands.tsx +36 -55
- package/src/extensions/SlashMenu/index.ts +1 -6
- package/src/extensions/TextAlignment/TextAlignmentExtension.ts +75 -0
- package/src/extensions/TextColor/TextColorExtension.ts +54 -0
- package/src/extensions/TextColor/TextColorMark.ts +62 -0
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +4 -4
- package/src/extensions/UniqueID/UniqueID.ts +6 -0
- package/src/index.ts +2 -1
- package/src/shared/EditorElement.ts +12 -6
- package/src/shared/plugins/suggestion/SuggestionItem.ts +0 -9
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +191 -228
- package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +2 -2
- package/types/src/BlockNoteEditor.d.ts +1 -1
- package/types/src/BlockNoteExtensions.d.ts +1 -3
- package/types/src/api/Document.d.ts +5 -0
- package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +9 -0
- package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +9 -0
- package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +3 -2
- package/types/src/extensions/Blocks/apiTypes.d.ts +16 -0
- package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +1 -1
- package/types/src/extensions/Blocks/nodes/BlockAttributes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +21 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/BlockContentTypes.d.ts +4 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContentTypes.d.ts +4 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContentTypes.d.ts +2 -0
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +9 -5
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +1 -1
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +6 -11
- package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +24 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +18 -8
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +1 -1
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +5 -5
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +2 -2
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +1 -1
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -19
- package/types/src/extensions/SlashMenu/defaultSlashCommands.d.ts +5 -0
- package/types/src/extensions/SlashMenu/index.d.ts +1 -2
- package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +9 -0
- package/types/src/extensions/TextColor/TextColorExtension.d.ts +9 -0
- package/types/src/extensions/TextColor/TextColorMark.d.ts +9 -0
- package/types/src/index.d.ts +2 -1
- package/types/src/shared/EditorElement.d.ts +6 -2
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +0 -6
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +11 -25
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +6 -6
- package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts +0 -177
- package/src/extensions/Paragraph/FixedParagraph.ts +0 -12
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://github.com/yousefed/blocknote",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.4-alpha.7",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"types",
|
|
@@ -49,35 +49,28 @@
|
|
|
49
49
|
"@emotion/cache": "^11.10.5",
|
|
50
50
|
"@emotion/serialize": "^1.1.1",
|
|
51
51
|
"@emotion/utils": "^1.2.0",
|
|
52
|
-
"@tiptap/core": "2.0.0-beta.
|
|
53
|
-
"@tiptap/extension-bold": "2.0.0-beta.
|
|
54
|
-
"@tiptap/extension-code": "2.0.0-beta.
|
|
55
|
-
"@tiptap/extension-collaboration": "2.0.0-beta.
|
|
56
|
-
"@tiptap/extension-collaboration-cursor": "2.0.0-beta.
|
|
57
|
-
"@tiptap/extension-dropcursor": "2.0.0-beta.
|
|
58
|
-
"@tiptap/extension-gapcursor": "2.0.0-beta.
|
|
59
|
-
"@tiptap/extension-hard-break": "2.0.0-beta.
|
|
60
|
-
"@tiptap/extension-history": "2.0.0-beta.
|
|
61
|
-
"@tiptap/extension-horizontal-rule": "2.0.0-beta.
|
|
62
|
-
"@tiptap/extension-italic": "2.0.0-beta.
|
|
63
|
-
"@tiptap/extension-link": "2.0.0-beta.
|
|
64
|
-
"@tiptap/extension-paragraph": "2.0.0-beta.
|
|
65
|
-
"@tiptap/extension-strike": "2.0.0-beta.
|
|
66
|
-
"@tiptap/extension-text": "2.0.0-beta.
|
|
67
|
-
"@tiptap/extension-underline": "2.0.0-beta.
|
|
52
|
+
"@tiptap/core": "2.0.0-beta.217",
|
|
53
|
+
"@tiptap/extension-bold": "2.0.0-beta.217",
|
|
54
|
+
"@tiptap/extension-code": "2.0.0-beta.217",
|
|
55
|
+
"@tiptap/extension-collaboration": "2.0.0-beta.217",
|
|
56
|
+
"@tiptap/extension-collaboration-cursor": "2.0.0-beta.217",
|
|
57
|
+
"@tiptap/extension-dropcursor": "2.0.0-beta.217",
|
|
58
|
+
"@tiptap/extension-gapcursor": "2.0.0-beta.217",
|
|
59
|
+
"@tiptap/extension-hard-break": "2.0.0-beta.217",
|
|
60
|
+
"@tiptap/extension-history": "2.0.0-beta.217",
|
|
61
|
+
"@tiptap/extension-horizontal-rule": "2.0.0-beta.217",
|
|
62
|
+
"@tiptap/extension-italic": "2.0.0-beta.217",
|
|
63
|
+
"@tiptap/extension-link": "2.0.0-beta.217",
|
|
64
|
+
"@tiptap/extension-paragraph": "2.0.0-beta.217",
|
|
65
|
+
"@tiptap/extension-strike": "2.0.0-beta.217",
|
|
66
|
+
"@tiptap/extension-text": "2.0.0-beta.217",
|
|
67
|
+
"@tiptap/extension-underline": "2.0.0-beta.217",
|
|
68
|
+
"@tiptap/pm": "2.0.0-beta.217",
|
|
68
69
|
"lodash": "^4.17.21",
|
|
69
|
-
"prosemirror-commands": "^1.5.0",
|
|
70
|
-
"prosemirror-dropcursor": "1.5.0",
|
|
71
|
-
"prosemirror-gapcursor": "^1.3.1",
|
|
72
|
-
"prosemirror-history": "^1.3.0",
|
|
73
|
-
"prosemirror-keymap": "^1.2.0",
|
|
74
|
-
"prosemirror-model": "~1.18.3",
|
|
75
|
-
"prosemirror-schema-list": "^1.2.2",
|
|
76
|
-
"prosemirror-state": "^1.4.2",
|
|
77
|
-
"prosemirror-transform": "^1.7.1",
|
|
78
|
-
"prosemirror-view": "^1.30.0",
|
|
79
70
|
"uuid": "^8.3.2",
|
|
80
|
-
"y-prosemirror": "1.0.20"
|
|
71
|
+
"y-prosemirror": "1.0.20",
|
|
72
|
+
"y-protocols": "1.0.5",
|
|
73
|
+
"yjs": "13.5.44"
|
|
81
74
|
},
|
|
82
75
|
"devDependencies": {
|
|
83
76
|
"@types/lodash": "^4.14.179",
|
|
@@ -102,5 +95,5 @@
|
|
|
102
95
|
"access": "public",
|
|
103
96
|
"registry": "https://registry.npmjs.org/"
|
|
104
97
|
},
|
|
105
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "d1d1756de514dedd5ef9c0d297b45db9b5ba8d02"
|
|
106
99
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Extensions, extensions } from "@tiptap/core";
|
|
2
2
|
|
|
3
|
-
import { Node } from "@tiptap/core";
|
|
4
3
|
import Bold from "@tiptap/extension-bold";
|
|
5
4
|
import Code from "@tiptap/extension-code";
|
|
6
5
|
import DropCursor from "@tiptap/extension-dropcursor";
|
|
@@ -16,7 +15,6 @@ import blockStyles from "./extensions/Blocks/nodes/Block.module.css";
|
|
|
16
15
|
import { FormattingToolbarExtension } from "./extensions/FormattingToolbar/FormattingToolbarExtension";
|
|
17
16
|
import { DraggableBlocksExtension } from "./extensions/DraggableBlocks/DraggableBlocksExtension";
|
|
18
17
|
import HyperlinkMark from "./extensions/HyperlinkToolbar/HyperlinkMark";
|
|
19
|
-
import { FixedParagraph } from "./extensions/Paragraph/FixedParagraph";
|
|
20
18
|
import { Placeholder } from "./extensions/Placeholder/PlaceholderExtension";
|
|
21
19
|
import SlashMenuExtension from "./extensions/SlashMenu";
|
|
22
20
|
import { TrailingNode } from "./extensions/TrailingNode/TrailingNodeExtension";
|
|
@@ -27,12 +25,11 @@ import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsM
|
|
|
27
25
|
import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
|
|
28
26
|
import { Link } from "@tiptap/extension-link";
|
|
29
27
|
import { SlashMenuItem } from "./extensions/SlashMenu/SlashMenuItem";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
28
|
+
import { BackgroundColorMark } from "./extensions/BackgroundColor/BackgroundColorMark";
|
|
29
|
+
import { TextColorMark } from "./extensions/TextColor/TextColorMark";
|
|
30
|
+
import { BackgroundColorExtension } from "./extensions/BackgroundColor/BackgroundColorExtension";
|
|
31
|
+
import { TextColorExtension } from "./extensions/TextColor/TextColorExtension";
|
|
32
|
+
import { TextAlignmentExtension } from "./extensions/TextAlignment/TextAlignmentExtension";
|
|
36
33
|
|
|
37
34
|
export type UiFactories = Partial<{
|
|
38
35
|
formattingToolbarFactory: FormattingToolbarFactory;
|
|
@@ -64,7 +61,7 @@ export const getBlockNoteExtensions = (uiFactories: UiFactories) => {
|
|
|
64
61
|
showOnlyCurrent: false,
|
|
65
62
|
}),
|
|
66
63
|
UniqueID.configure({
|
|
67
|
-
types: ["
|
|
64
|
+
types: ["blockContainer"],
|
|
68
65
|
}),
|
|
69
66
|
HardBreak,
|
|
70
67
|
// Comments,
|
|
@@ -78,7 +75,11 @@ export const getBlockNoteExtensions = (uiFactories: UiFactories) => {
|
|
|
78
75
|
Italic,
|
|
79
76
|
Strike,
|
|
80
77
|
Underline,
|
|
81
|
-
|
|
78
|
+
TextColorMark,
|
|
79
|
+
TextColorExtension,
|
|
80
|
+
BackgroundColorMark,
|
|
81
|
+
BackgroundColorExtension,
|
|
82
|
+
TextAlignmentExtension,
|
|
82
83
|
|
|
83
84
|
// custom blocks:
|
|
84
85
|
...blocks,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
|
|
3
|
+
|
|
4
|
+
declare module "@tiptap/core" {
|
|
5
|
+
interface Commands<ReturnType> {
|
|
6
|
+
blockBackgroundColor: {
|
|
7
|
+
setBlockBackgroundColor: (
|
|
8
|
+
posInBlock: number,
|
|
9
|
+
color: string
|
|
10
|
+
) => ReturnType;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const BackgroundColorExtension = Extension.create({
|
|
16
|
+
name: "blockBackgroundColor",
|
|
17
|
+
|
|
18
|
+
addGlobalAttributes() {
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
types: ["blockContainer"],
|
|
22
|
+
attributes: {
|
|
23
|
+
backgroundColor: {
|
|
24
|
+
default: "default",
|
|
25
|
+
parseHTML: (element) =>
|
|
26
|
+
element.hasAttribute("data-background-color")
|
|
27
|
+
? element.getAttribute("data-background-color")
|
|
28
|
+
: "default",
|
|
29
|
+
renderHTML: (attributes) =>
|
|
30
|
+
attributes.backgroundColor !== "default" && {
|
|
31
|
+
"data-background-color": attributes.backgroundColor,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
addCommands() {
|
|
40
|
+
return {
|
|
41
|
+
setBlockBackgroundColor:
|
|
42
|
+
(posInBlock, color) =>
|
|
43
|
+
({ state, view }) => {
|
|
44
|
+
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
45
|
+
if (blockInfo === undefined) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
state.tr.setNodeAttribute(
|
|
50
|
+
blockInfo.startPos - 1,
|
|
51
|
+
"backgroundColor",
|
|
52
|
+
color
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
view.focus();
|
|
56
|
+
|
|
57
|
+
return true;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Mark } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
declare module "@tiptap/core" {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
backgroundColor: {
|
|
6
|
+
setBackgroundColor: (color: string) => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const BackgroundColorMark = Mark.create({
|
|
12
|
+
name: "backgroundColor",
|
|
13
|
+
|
|
14
|
+
addAttributes() {
|
|
15
|
+
return {
|
|
16
|
+
color: {
|
|
17
|
+
default: undefined,
|
|
18
|
+
parseHTML: (element) => element.getAttribute("data-background-color"),
|
|
19
|
+
renderHTML: (attributes) => ({
|
|
20
|
+
"data-background-color": attributes.color,
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
parseHTML() {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
tag: "span",
|
|
30
|
+
getAttrs: (element) => {
|
|
31
|
+
if (typeof element === "string") {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (element.hasAttribute("data-background-color")) {
|
|
36
|
+
return { color: element.getAttribute("data-background-color") };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return false;
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
renderHTML({ HTMLAttributes }) {
|
|
46
|
+
return ["span", HTMLAttributes, 0];
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
addCommands() {
|
|
50
|
+
return {
|
|
51
|
+
setBackgroundColor:
|
|
52
|
+
(color) =>
|
|
53
|
+
({ commands }) => {
|
|
54
|
+
if (color !== "default") {
|
|
55
|
+
return commands.setMark(this.name, { color: color });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return commands.unsetMark(this.name);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
combineTransactionSteps,
|
|
3
|
-
findChildren,
|
|
4
|
-
getChangedRanges,
|
|
5
|
-
} from "@tiptap/core";
|
|
1
|
+
import { findChildren } from "@tiptap/core";
|
|
6
2
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
7
3
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
8
4
|
|
|
9
5
|
const PLUGIN_KEY = new PluginKey(`previous-blocks`);
|
|
10
6
|
|
|
11
7
|
const nodeAttributes: Record<string, string> = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
// Numbered List Items
|
|
9
|
+
index: "index",
|
|
10
|
+
// Headings
|
|
11
|
+
level: "level",
|
|
12
|
+
// All Blocks
|
|
15
13
|
type: "type",
|
|
16
14
|
depth: "depth",
|
|
17
15
|
"depth-change": "depth-change",
|
|
@@ -31,7 +29,7 @@ export const PreviousBlockTypePlugin = () => {
|
|
|
31
29
|
view(_editorView) {
|
|
32
30
|
return {
|
|
33
31
|
update: async (view, _prevState) => {
|
|
34
|
-
if (this.key?.getState(view.state).
|
|
32
|
+
if (this.key?.getState(view.state).updatedBlocks.size > 0) {
|
|
35
33
|
// use setTimeout 0 to clear the decorations so that at least
|
|
36
34
|
// for one DOM-render the decorations have been applied
|
|
37
35
|
setTimeout(() => {
|
|
@@ -46,114 +44,122 @@ export const PreviousBlockTypePlugin = () => {
|
|
|
46
44
|
state: {
|
|
47
45
|
init() {
|
|
48
46
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
// Block attributes, by block ID, from just before the previous transaction.
|
|
48
|
+
prevTransactionOldBlockAttrs: {} as any,
|
|
49
|
+
// Block attributes, by block ID, from just before the current transaction.
|
|
50
|
+
currentTransactionOldBlockAttrs: {} as any,
|
|
51
|
+
// Set of IDs of blocks whose attributes changed from the current transaction.
|
|
52
|
+
updatedBlocks: new Set<string>(),
|
|
51
53
|
};
|
|
52
54
|
},
|
|
53
55
|
|
|
54
56
|
apply(transaction, prev, oldState, newState) {
|
|
55
|
-
prev.
|
|
56
|
-
prev.
|
|
57
|
+
prev.currentTransactionOldBlockAttrs = {};
|
|
58
|
+
prev.updatedBlocks.clear();
|
|
59
|
+
|
|
57
60
|
if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {
|
|
58
61
|
return prev;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
//
|
|
63
|
-
const changes = getChangedRanges(transform);
|
|
64
|
-
|
|
65
|
-
// TODO: instead of iterating through the entire document, only check nodes affected by the transactions
|
|
64
|
+
// TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will
|
|
65
|
+
// also probably require checking nodes affected by the previous transaction too.
|
|
66
66
|
// We didn't get this to work yet:
|
|
67
|
+
// const transform = combineTransactionSteps(oldState.doc, [transaction]);
|
|
68
|
+
// // const { mapping } = transform;
|
|
69
|
+
// const changes = getChangedRanges(transform);
|
|
70
|
+
//
|
|
67
71
|
// changes.forEach(({ oldRange, newRange }) => {
|
|
68
72
|
// const oldNodes = findChildrenInRange(
|
|
69
73
|
// oldState.doc,
|
|
70
74
|
// oldRange,
|
|
71
75
|
// (node) => node.attrs.id
|
|
72
76
|
// );
|
|
73
|
-
|
|
77
|
+
//
|
|
74
78
|
// const newNodes = findChildrenInRange(
|
|
75
79
|
// newState.doc,
|
|
76
80
|
// newRange,
|
|
77
81
|
// (node) => node.attrs.id
|
|
78
82
|
// );
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
oldAttrs
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
: true;
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) && // TODO: faster deep equal?
|
|
136
|
-
shouldUpdate
|
|
137
|
-
) {
|
|
138
|
-
(oldAttrs as any)["depth-change"] =
|
|
139
|
-
oldAttrs.depth - newAttrs.depth;
|
|
140
|
-
prev.prevBlockAttrs[node.node.attrs.id] = oldAttrs;
|
|
141
|
-
|
|
142
|
-
// for debugging:
|
|
143
|
-
console.log(
|
|
144
|
-
"id:",
|
|
145
|
-
node.node.attrs.id,
|
|
146
|
-
"previousBlockTypePlugin changes detected, oldAttrs",
|
|
147
|
-
oldAttrs,
|
|
148
|
-
"new",
|
|
149
|
-
newAttrs
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
prev.needsUpdate = true;
|
|
84
|
+
const currentTransactionOriginalOldBlockAttrs = {} as any;
|
|
85
|
+
|
|
86
|
+
const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);
|
|
87
|
+
const oldNodesById = new Map(
|
|
88
|
+
oldNodes.map((node) => [node.node.attrs.id, node])
|
|
89
|
+
);
|
|
90
|
+
const newNodes = findChildren(newState.doc, (node) => node.attrs.id);
|
|
91
|
+
|
|
92
|
+
// Traverses all block containers in the new editor state.
|
|
93
|
+
for (let node of newNodes) {
|
|
94
|
+
const oldNode = oldNodesById.get(node.node.attrs.id);
|
|
95
|
+
|
|
96
|
+
const oldContentNode = oldNode?.node.firstChild;
|
|
97
|
+
const newContentNode = node.node.firstChild;
|
|
98
|
+
|
|
99
|
+
if (oldNode && oldContentNode && newContentNode) {
|
|
100
|
+
const newAttrs = {
|
|
101
|
+
index: newContentNode.attrs.index,
|
|
102
|
+
level: newContentNode.attrs.level,
|
|
103
|
+
type: newContentNode.type.name,
|
|
104
|
+
depth: newState.doc.resolve(node.pos).depth,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
let oldAttrs = {
|
|
108
|
+
index: oldContentNode.attrs.index,
|
|
109
|
+
level: oldContentNode.attrs.level,
|
|
110
|
+
type: oldContentNode.type.name,
|
|
111
|
+
depth: oldState.doc.resolve(oldNode.pos).depth,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =
|
|
115
|
+
oldAttrs;
|
|
116
|
+
|
|
117
|
+
// Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:
|
|
118
|
+
// { "orderedListIndexing": true }
|
|
119
|
+
// These appended transactions happen immediately after any transaction which causes ordered list item
|
|
120
|
+
// indices to require updating, including those which trigger animations. Therefore, these animations are
|
|
121
|
+
// immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only
|
|
122
|
+
// the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the
|
|
123
|
+
// "orderedListIndexing" metadata, so the correct animation can be re-triggered.
|
|
124
|
+
if (transaction.getMeta("numberedListIndexing")) {
|
|
125
|
+
// If the block existed before the transaction, gets the attributes from before the previous transaction
|
|
126
|
+
// (i.e. the transaction that caused list item indices to need updating).
|
|
127
|
+
if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {
|
|
128
|
+
oldAttrs =
|
|
129
|
+
prev.prevTransactionOldBlockAttrs[node.node.attrs.id];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Stops list item indices themselves being animated (looks smoother), unless the block's content type is
|
|
133
|
+
// changing from a numbered list item to something else.
|
|
134
|
+
if (newAttrs.type === "numberedListItem") {
|
|
135
|
+
oldAttrs.index = newAttrs.index;
|
|
153
136
|
}
|
|
154
137
|
}
|
|
138
|
+
|
|
139
|
+
prev.currentTransactionOldBlockAttrs[node.node.attrs.id] = oldAttrs;
|
|
140
|
+
|
|
141
|
+
// TODO: faster deep equal?
|
|
142
|
+
if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {
|
|
143
|
+
(oldAttrs as any)["depth-change"] =
|
|
144
|
+
oldAttrs.depth - newAttrs.depth;
|
|
145
|
+
|
|
146
|
+
// for debugging:
|
|
147
|
+
// console.log(
|
|
148
|
+
// "id:",
|
|
149
|
+
// node.node.attrs.id,
|
|
150
|
+
// "previousBlockTypePlugin changes detected, oldAttrs",
|
|
151
|
+
// oldAttrs,
|
|
152
|
+
// "new",
|
|
153
|
+
// newAttrs
|
|
154
|
+
// );
|
|
155
|
+
|
|
156
|
+
prev.updatedBlocks.add(node.node.attrs.id);
|
|
157
|
+
}
|
|
155
158
|
}
|
|
156
|
-
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
prev.prevTransactionOldBlockAttrs =
|
|
162
|
+
currentTransactionOriginalOldBlockAttrs;
|
|
157
163
|
|
|
158
164
|
return prev;
|
|
159
165
|
},
|
|
@@ -161,8 +167,7 @@ export const PreviousBlockTypePlugin = () => {
|
|
|
161
167
|
props: {
|
|
162
168
|
decorations(state) {
|
|
163
169
|
const pluginState = (this as Plugin).getState(state);
|
|
164
|
-
if (
|
|
165
|
-
// console.log("0");
|
|
170
|
+
if (pluginState.updatedBlocks.size === 0) {
|
|
166
171
|
return undefined;
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -170,29 +175,30 @@ export const PreviousBlockTypePlugin = () => {
|
|
|
170
175
|
|
|
171
176
|
state.doc.descendants((node, pos) => {
|
|
172
177
|
if (!node.attrs.id) {
|
|
173
|
-
// console.log("1");
|
|
174
178
|
return;
|
|
175
179
|
}
|
|
176
|
-
|
|
177
|
-
if (!
|
|
178
|
-
// console.log("2");
|
|
180
|
+
|
|
181
|
+
if (!pluginState.updatedBlocks.has(node.attrs.id)) {
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
181
184
|
|
|
182
|
-
const
|
|
185
|
+
const prevAttrs =
|
|
186
|
+
pluginState.currentTransactionOldBlockAttrs[node.attrs.id];
|
|
187
|
+
const decorationAttrs: any = {};
|
|
188
|
+
|
|
183
189
|
for (let [nodeAttr, val] of Object.entries(prevAttrs)) {
|
|
184
|
-
|
|
190
|
+
decorationAttrs["data-prev-" + nodeAttributes[nodeAttr]] =
|
|
185
191
|
val || "none";
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
// for debugging:
|
|
189
|
-
console.log(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
195
|
+
// console.log(
|
|
196
|
+
// "previousBlockTypePlugin committing decorations",
|
|
197
|
+
// decorationAttrs
|
|
198
|
+
// );
|
|
193
199
|
|
|
194
200
|
const decoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
195
|
-
...
|
|
201
|
+
...decorationAttrs,
|
|
196
202
|
});
|
|
197
203
|
|
|
198
204
|
decorations.push(decoration);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type BlockSpec<
|
|
2
|
+
// Type of the block.
|
|
3
|
+
// Examples might include: "paragraph", "heading", or "bulletListItem".
|
|
4
|
+
Type extends string,
|
|
5
|
+
// Changeable props which affect the block's behaviour or appearance.
|
|
6
|
+
// An example might be: { textAlignment: "left" | "right" | "center" | "justify" } for a paragraph block.
|
|
7
|
+
Props extends Record<string, string>
|
|
8
|
+
> = {
|
|
9
|
+
type: Type;
|
|
10
|
+
props: Props;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type BlockSpecUpdate<Spec> = Spec extends BlockSpec<
|
|
14
|
+
infer Type,
|
|
15
|
+
infer Props
|
|
16
|
+
>
|
|
17
|
+
? {
|
|
18
|
+
type: Type;
|
|
19
|
+
props?: Partial<Props>;
|
|
20
|
+
}
|
|
21
|
+
: never;
|
|
22
|
+
|
|
23
|
+
export type NumberedListItemBlock = BlockSpec<"numberedListItem", {}>;
|
|
24
|
+
|
|
25
|
+
export type BulletListItemBlock = BlockSpec<"bulletListItem", {}>;
|
|
26
|
+
|
|
27
|
+
export type HeadingBlock = BlockSpec<
|
|
28
|
+
"heading",
|
|
29
|
+
{
|
|
30
|
+
level: "1" | "2" | "3";
|
|
31
|
+
}
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
export type ParagraphBlock = BlockSpec<"paragraph", {}>;
|
|
35
|
+
|
|
36
|
+
export type Block =
|
|
37
|
+
| ParagraphBlock
|
|
38
|
+
| HeadingBlock
|
|
39
|
+
| BulletListItemBlock
|
|
40
|
+
| NumberedListItemBlock;
|
|
41
|
+
|
|
42
|
+
export type BlockUpdate = BlockSpecUpdate<Block>;
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
TODO:
|
|
46
|
+
1) guard read / writes (now we just pass on internal node attrs)
|
|
47
|
+
2) where to locate this code / types
|
|
48
|
+
*/
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Node } from "@tiptap/core";
|
|
2
|
-
import {
|
|
2
|
+
import { BlockContainer } from "./nodes/BlockContainer";
|
|
3
3
|
import { BlockGroup } from "./nodes/BlockGroup";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { ParagraphBlockContent } from "./nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent";
|
|
5
|
+
import { HeadingBlockContent } from "./nodes/BlockContent/HeadingBlockContent/HeadingBlockContent";
|
|
6
|
+
import { BulletListItemBlockContent } from "./nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent";
|
|
7
|
+
import { NumberedListItemBlockContent } from "./nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent";
|
|
7
8
|
|
|
8
9
|
export const blocks: any[] = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
ParagraphBlockContent,
|
|
11
|
+
HeadingBlockContent,
|
|
12
|
+
BulletListItemBlockContent,
|
|
13
|
+
NumberedListItemBlockContent,
|
|
14
|
+
BlockContainer,
|
|
13
15
|
BlockGroup,
|
|
14
16
|
Node.create({
|
|
15
17
|
name: "doc",
|