@blocknote/core 0.11.2 → 0.12.1
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 +13 -17
- package/dist/blocknote.js +1662 -1447
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +6 -6
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +7 -3
- package/src/api/blockManipulation/blockManipulation.test.ts +19 -15
- package/src/api/blockManipulation/blockManipulation.ts +107 -17
- package/src/api/exporters/html/externalHTMLExporter.ts +3 -7
- package/src/api/exporters/html/htmlConversion.test.ts +6 -3
- package/src/api/exporters/html/internalHTMLSerializer.ts +3 -7
- package/src/api/exporters/html/util/sharedHTMLConversion.ts +3 -3
- package/src/api/exporters/markdown/markdownExporter.test.ts +7 -3
- package/src/api/exporters/markdown/markdownExporter.ts +2 -6
- package/src/api/getCurrentBlockContentType.ts +14 -0
- package/src/api/nodeConversions/nodeConversions.test.ts +14 -7
- package/src/api/nodeConversions/nodeConversions.ts +1 -2
- package/src/api/parsers/html/parseHTML.test.ts +5 -1
- package/src/api/parsers/html/parseHTML.ts +2 -6
- package/src/api/parsers/html/util/nestedLists.ts +11 -1
- package/src/api/parsers/markdown/parseMarkdown.test.ts +3 -0
- package/src/api/parsers/markdown/parseMarkdown.ts +2 -6
- package/src/api/testUtil/cases/customBlocks.ts +18 -16
- package/src/api/testUtil/cases/customInlineContent.ts +12 -13
- package/src/api/testUtil/cases/customStyles.ts +12 -10
- package/src/api/testUtil/index.ts +4 -2
- package/src/api/testUtil/partialBlockTestUtil.ts +2 -6
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +50 -21
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +1 -2
- package/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +8 -1
- package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +18 -5
- package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +7 -1
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +18 -5
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +14 -5
- package/src/blocks/defaultBlockHelpers.ts +3 -3
- package/src/blocks/defaultBlockTypeGuards.ts +84 -0
- package/src/blocks/defaultBlocks.ts +29 -3
- package/src/editor/Block.css +2 -31
- package/src/editor/BlockNoteEditor.ts +223 -267
- package/src/editor/BlockNoteExtensions.ts +5 -2
- package/src/editor/BlockNoteSchema.ts +98 -0
- package/src/editor/BlockNoteTipTapEditor.ts +162 -0
- package/src/editor/cursorPositionTypes.ts +2 -6
- package/src/editor/editor.css +0 -1
- package/src/editor/selectionTypes.ts +2 -6
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +22 -29
- package/src/extensions/{ImageToolbar → ImagePanel}/ImageToolbarPlugin.ts +54 -60
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +330 -0
- package/src/extensions/Placeholder/PlaceholderExtension.ts +81 -88
- package/src/extensions/SideMenu/SideMenuPlugin.ts +55 -56
- package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +8 -0
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +353 -0
- package/src/extensions/{SlashMenu/defaultSlashMenuItems.ts → SuggestionMenu/getDefaultSlashMenuItems.ts} +119 -89
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +62 -45
- package/src/extensions-shared/UiElementPosition.ts +4 -0
- package/src/index.ts +8 -8
- package/src/pm-nodes/BlockContainer.ts +5 -5
- package/src/schema/blocks/types.ts +15 -15
- package/src/schema/inlineContent/createSpec.ts +2 -2
- package/src/schema/inlineContent/types.ts +1 -1
- package/src/util/browser.ts +6 -4
- package/src/util/typescript.ts +7 -4
- package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -1
- package/types/src/api/exporters/html/externalHTMLExporter.d.ts +2 -1
- package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +2 -1
- package/types/src/api/exporters/markdown/markdownExporter.d.ts +2 -1
- package/types/src/api/getCurrentBlockContentType.d.ts +2 -0
- package/types/src/api/nodeConversions/nodeConversions.d.ts +2 -1
- package/types/src/api/parsers/html/parseHTML.d.ts +2 -1
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -1
- package/types/src/api/testUtil/cases/customBlocks.d.ts +72 -13
- package/types/src/api/testUtil/cases/customInlineContent.d.ts +281 -6
- package/types/src/api/testUtil/cases/customStyles.d.ts +247 -13
- package/types/src/api/testUtil/index.d.ts +4 -2
- package/types/src/api/testUtil/partialBlockTestUtil.d.ts +2 -1
- package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +6 -1
- package/types/src/blocks/defaultBlockHelpers.d.ts +2 -2
- package/types/src/blocks/defaultBlockTypeGuards.d.ts +24 -0
- package/types/src/blocks/defaultBlocks.d.ts +21 -15
- package/types/src/editor/BlockNoteEditor.d.ts +51 -56
- package/types/src/editor/BlockNoteExtensions.d.ts +1 -0
- package/types/src/editor/BlockNoteSchema.d.ts +34 -0
- package/types/src/editor/BlockNoteTipTapEditor.d.ts +28 -0
- package/types/src/editor/cursorPositionTypes.d.ts +2 -1
- package/types/src/editor/selectionTypes.d.ts +2 -1
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -6
- package/types/src/extensions/ImagePanel/ImageToolbarPlugin.d.ts +32 -0
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +40 -0
- package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +2 -15
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +8 -7
- package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +8 -0
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +31 -0
- package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +10 -0
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +7 -7
- package/types/src/extensions-shared/UiElementPosition.d.ts +4 -0
- package/types/src/index.d.ts +8 -8
- package/types/src/pm-nodes/BlockContainer.d.ts +3 -2
- package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
- package/types/src/schema/blocks/types.d.ts +15 -15
- package/types/src/schema/inlineContent/types.d.ts +1 -1
- package/types/src/util/browser.d.ts +1 -0
- package/types/src/util/typescript.d.ts +1 -0
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +0 -335
- package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +0 -12
- package/src/extensions/SlashMenu/SlashMenuPlugin.ts +0 -53
- package/src/extensions-shared/BaseUiElementTypes.ts +0 -8
- package/src/extensions-shared/README.md +0 -3
- package/src/extensions-shared/suggestion/SuggestionItem.ts +0 -3
- package/src/extensions-shared/suggestion/SuggestionPlugin.ts +0 -448
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +0 -38
- package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +0 -31
- package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +0 -7
- package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +0 -13
- package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +0 -3
- package/types/src/extensions-shared/BaseUiElementTypes.d.ts +0 -7
- package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +0 -3
- package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +0 -36
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
- /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
- /package/src/{assets/fonts-inter.css → fonts/inter.css} +0 -0
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { DOMParser, Schema } from "prosemirror-model";
|
|
2
|
-
import {
|
|
3
|
-
Block,
|
|
4
|
-
BlockSchema,
|
|
5
|
-
InlineContentSchema,
|
|
6
|
-
StyleSchema,
|
|
7
|
-
} from "../../../schema";
|
|
2
|
+
import { BlockSchema, InlineContentSchema, StyleSchema } from "../../../schema";
|
|
8
3
|
|
|
4
|
+
import { Block } from "../../../blocks/defaultBlocks";
|
|
9
5
|
import { nodeToBlock } from "../../nodeConversions/nodeConversions";
|
|
10
6
|
import { nestedListsToBlockNoteStructure } from "./util/nestedLists";
|
|
11
7
|
export async function HTMLToBlocks<
|
|
@@ -99,11 +99,21 @@ function createGroups(element: HTMLElement) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204
|
|
103
|
+
// https://github.com/TypeCellOS/BlockNote/issues/601
|
|
104
|
+
let _detachedDoc: Document | null = null;
|
|
105
|
+
function detachedDoc() {
|
|
106
|
+
return (
|
|
107
|
+
_detachedDoc ||
|
|
108
|
+
(_detachedDoc = document.implementation.createHTMLDocument("title"))
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
export function nestedListsToBlockNoteStructure(
|
|
103
113
|
elementOrHTML: HTMLElement | string
|
|
104
114
|
) {
|
|
105
115
|
if (typeof elementOrHTML === "string") {
|
|
106
|
-
const element =
|
|
116
|
+
const element = detachedDoc().createElement("div");
|
|
107
117
|
element.innerHTML = elementOrHTML;
|
|
108
118
|
elementOrHTML = element;
|
|
109
119
|
}
|
|
@@ -6,12 +6,15 @@ async function parseMarkdownAndCompareSnapshots(
|
|
|
6
6
|
snapshotName: string
|
|
7
7
|
) {
|
|
8
8
|
const editor = BlockNoteEditor.create();
|
|
9
|
+
const div = document.createElement("div");
|
|
10
|
+
editor.mount(div);
|
|
9
11
|
const blocks = await editor.tryParseMarkdownToBlocks(md);
|
|
10
12
|
|
|
11
13
|
const snapshotPath = "./__snapshots__/" + snapshotName + ".json";
|
|
12
14
|
expect(JSON.stringify(blocks, undefined, 2)).toMatchFileSnapshot(
|
|
13
15
|
snapshotPath
|
|
14
16
|
);
|
|
17
|
+
editor.mount(undefined);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
describe("Parse Markdown", () => {
|
|
@@ -4,12 +4,8 @@ import remarkGfm from "remark-gfm";
|
|
|
4
4
|
import remarkParse from "remark-parse";
|
|
5
5
|
import remarkRehype, { defaultHandlers } from "remark-rehype";
|
|
6
6
|
import { unified } from "unified";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
BlockSchema,
|
|
10
|
-
InlineContentSchema,
|
|
11
|
-
StyleSchema,
|
|
12
|
-
} from "../../../schema";
|
|
7
|
+
import { Block } from "../../../blocks/defaultBlocks";
|
|
8
|
+
import { BlockSchema, InlineContentSchema, StyleSchema } from "../../../schema";
|
|
13
9
|
import { HTMLToBlocks } from "../html/parseHTML";
|
|
14
10
|
|
|
15
11
|
// modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { EditorTestCases } from "../index";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
imagePropSchema,
|
|
5
|
+
renderImage,
|
|
6
|
+
} from "../../../blocks/ImageBlockContent/ImageBlockContent";
|
|
7
|
+
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
|
|
4
8
|
import {
|
|
5
9
|
DefaultInlineContentSchema,
|
|
6
10
|
DefaultStyleSchema,
|
|
7
11
|
defaultBlockSpecs,
|
|
8
12
|
} from "../../../blocks/defaultBlocks";
|
|
9
13
|
import { defaultProps } from "../../../blocks/defaultProps";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
renderImage,
|
|
13
|
-
} from "../../../blocks/ImageBlockContent/ImageBlockContent";
|
|
14
|
-
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
|
|
14
|
+
import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
|
|
15
|
+
import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
|
|
15
16
|
import { createBlockSpec } from "../../../schema/blocks/createSpec";
|
|
16
|
-
import { BlockSchemaFromSpecs, BlockSpecs } from "../../../schema/blocks/types";
|
|
17
17
|
|
|
18
18
|
// This is a modified version of the default image block that does not implement
|
|
19
19
|
// a `serialize` function. It's used to test if the custom serializer by default
|
|
@@ -74,22 +74,24 @@ const SimpleCustomParagraph = createBlockSpec(
|
|
|
74
74
|
}
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
const schema = BlockNoteSchema.create({
|
|
78
|
+
blockSpecs: {
|
|
79
|
+
...defaultBlockSpecs,
|
|
80
|
+
simpleImage: SimpleImage,
|
|
81
|
+
customParagraph: CustomParagraph,
|
|
82
|
+
simpleCustomParagraph: SimpleCustomParagraph,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
83
85
|
|
|
84
86
|
export const customBlocksTestCases: EditorTestCases<
|
|
85
|
-
|
|
87
|
+
typeof schema.blockSchema,
|
|
86
88
|
DefaultInlineContentSchema,
|
|
87
89
|
DefaultStyleSchema
|
|
88
90
|
> = {
|
|
89
91
|
name: "custom blocks schema",
|
|
90
92
|
createEditor: () => {
|
|
91
93
|
return BlockNoteEditor.create({
|
|
92
|
-
|
|
94
|
+
schema,
|
|
93
95
|
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
|
|
94
96
|
});
|
|
95
97
|
},
|
|
@@ -98,7 +100,7 @@ export const customBlocksTestCases: EditorTestCases<
|
|
|
98
100
|
name: "simpleImage/button",
|
|
99
101
|
blocks: [
|
|
100
102
|
{
|
|
101
|
-
type: "simpleImage"
|
|
103
|
+
type: "simpleImage",
|
|
102
104
|
},
|
|
103
105
|
],
|
|
104
106
|
},
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { EditorTestCases } from "../index";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
|
|
4
4
|
import {
|
|
5
5
|
DefaultBlockSchema,
|
|
6
6
|
DefaultStyleSchema,
|
|
7
7
|
defaultInlineContentSpecs,
|
|
8
8
|
} from "../../../blocks/defaultBlocks";
|
|
9
|
-
import {
|
|
9
|
+
import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
|
|
10
|
+
import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
|
|
10
11
|
import { createInlineContentSpec } from "../../../schema/inlineContent/createSpec";
|
|
11
|
-
import {
|
|
12
|
-
InlineContentSchemaFromSpecs,
|
|
13
|
-
InlineContentSpecs,
|
|
14
|
-
} from "../../../schema/inlineContent/types";
|
|
15
12
|
|
|
16
13
|
const mention = createInlineContentSpec(
|
|
17
14
|
{
|
|
@@ -57,22 +54,24 @@ const tag = createInlineContentSpec(
|
|
|
57
54
|
}
|
|
58
55
|
);
|
|
59
56
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
const schema = BlockNoteSchema.create({
|
|
58
|
+
inlineContentSpecs: {
|
|
59
|
+
...defaultInlineContentSpecs,
|
|
60
|
+
mention,
|
|
61
|
+
tag,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
65
64
|
|
|
66
65
|
export const customInlineContentTestCases: EditorTestCases<
|
|
67
66
|
DefaultBlockSchema,
|
|
68
|
-
|
|
67
|
+
typeof schema.inlineContentSchema,
|
|
69
68
|
DefaultStyleSchema
|
|
70
69
|
> = {
|
|
71
70
|
name: "custom inline content schema",
|
|
72
71
|
createEditor: () => {
|
|
73
72
|
return BlockNoteEditor.create({
|
|
74
73
|
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
|
|
75
|
-
|
|
74
|
+
schema,
|
|
76
75
|
});
|
|
77
76
|
},
|
|
78
77
|
documents: [
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { EditorTestCases } from "../index";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
|
|
4
4
|
import {
|
|
5
5
|
DefaultBlockSchema,
|
|
6
6
|
DefaultInlineContentSchema,
|
|
7
7
|
defaultStyleSpecs,
|
|
8
8
|
} from "../../../blocks/defaultBlocks";
|
|
9
|
-
import {
|
|
9
|
+
import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
|
|
10
|
+
import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
|
|
10
11
|
import { createStyleSpec } from "../../../schema/styles/createSpec";
|
|
11
|
-
import { StyleSchemaFromSpecs, StyleSpecs } from "../../../schema/styles/types";
|
|
12
12
|
|
|
13
13
|
const small = createStyleSpec(
|
|
14
14
|
{
|
|
@@ -43,22 +43,24 @@ const fontSize = createStyleSpec(
|
|
|
43
43
|
}
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
const schema = BlockNoteSchema.create({
|
|
47
|
+
styleSpecs: {
|
|
48
|
+
...defaultStyleSpecs,
|
|
49
|
+
small,
|
|
50
|
+
fontSize,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
51
53
|
|
|
52
54
|
export const customStylesTestCases: EditorTestCases<
|
|
53
55
|
DefaultBlockSchema,
|
|
54
56
|
DefaultInlineContentSchema,
|
|
55
|
-
|
|
57
|
+
typeof schema.styleSchema
|
|
56
58
|
> = {
|
|
57
59
|
name: "custom style schema",
|
|
58
60
|
createEditor: () => {
|
|
59
61
|
return BlockNoteEditor.create({
|
|
60
62
|
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
|
|
61
|
-
|
|
63
|
+
schema,
|
|
62
64
|
});
|
|
63
65
|
},
|
|
64
66
|
documents: [
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { PartialBlock } from "../../blocks/defaultBlocks";
|
|
1
2
|
import { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
2
|
-
import { BlockSchema
|
|
3
|
+
import { BlockSchema } from "../../schema/blocks/types";
|
|
3
4
|
import { InlineContentSchema } from "../../schema/inlineContent/types";
|
|
4
5
|
import { StyleSchema } from "../../schema/styles/types";
|
|
6
|
+
import { NoInfer } from "../../util/typescript";
|
|
5
7
|
|
|
6
8
|
export type EditorTestCases<
|
|
7
9
|
B extends BlockSchema,
|
|
@@ -12,6 +14,6 @@ export type EditorTestCases<
|
|
|
12
14
|
createEditor: () => BlockNoteEditor<B, I, S>;
|
|
13
15
|
documents: Array<{
|
|
14
16
|
name: string;
|
|
15
|
-
blocks: PartialBlock<B
|
|
17
|
+
blocks: PartialBlock<NoInfer<B>, NoInfer<I>, NoInfer<S>>[];
|
|
16
18
|
}>;
|
|
17
19
|
};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
+
import { Block, PartialBlock } from "../../blocks/defaultBlocks";
|
|
1
2
|
import UniqueID from "../../extensions/UniqueID/UniqueID";
|
|
2
|
-
import {
|
|
3
|
-
Block,
|
|
4
|
-
BlockSchema,
|
|
5
|
-
PartialBlock,
|
|
6
|
-
TableContent,
|
|
7
|
-
} from "../../schema/blocks/types";
|
|
3
|
+
import { BlockSchema, TableContent } from "../../schema/blocks/types";
|
|
8
4
|
import {
|
|
9
5
|
InlineContent,
|
|
10
6
|
InlineContentSchema,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "../../schema";
|
|
7
7
|
import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers";
|
|
8
8
|
import { defaultProps } from "../defaultProps";
|
|
9
|
+
import { getCurrentBlockContentType } from "../../api/getCurrentBlockContentType";
|
|
9
10
|
|
|
10
11
|
export const headingPropSchema = {
|
|
11
12
|
...defaultProps,
|
|
@@ -45,6 +46,10 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
|
|
|
45
46
|
return new InputRule({
|
|
46
47
|
find: new RegExp(`^(#{${level}})\\s$`),
|
|
47
48
|
handler: ({ state, chain, range }) => {
|
|
49
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
chain()
|
|
49
54
|
.BNUpdateBlock(state.selection.from, {
|
|
50
55
|
type: "heading",
|
|
@@ -62,27 +67,51 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
|
|
|
62
67
|
|
|
63
68
|
addKeyboardShortcuts() {
|
|
64
69
|
return {
|
|
65
|
-
"Mod-Alt-1": () =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
"Mod-Alt-1": () => {
|
|
71
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return this.editor.commands.BNUpdateBlock(
|
|
76
|
+
this.editor.state.selection.anchor,
|
|
77
|
+
{
|
|
78
|
+
type: "heading",
|
|
79
|
+
props: {
|
|
80
|
+
level: 1 as any,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
"Mod-Alt-2": () => {
|
|
86
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.editor.commands.BNUpdateBlock(
|
|
91
|
+
this.editor.state.selection.anchor,
|
|
92
|
+
{
|
|
93
|
+
type: "heading",
|
|
94
|
+
props: {
|
|
95
|
+
level: 2 as any,
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
"Mod-Alt-3": () => {
|
|
101
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return this.editor.commands.BNUpdateBlock(
|
|
106
|
+
this.editor.state.selection.anchor,
|
|
107
|
+
{
|
|
108
|
+
type: "heading",
|
|
109
|
+
props: {
|
|
110
|
+
level: 3 as any,
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
},
|
|
86
115
|
};
|
|
87
116
|
},
|
|
88
117
|
parseHTML() {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
2
|
-
import { imageToolbarPluginKey } from "../../extensions/ImageToolbar/ImageToolbarPlugin";
|
|
3
2
|
|
|
4
3
|
import {
|
|
5
4
|
BlockFromConfig,
|
|
@@ -235,7 +234,7 @@ export const renderImage = (
|
|
|
235
234
|
// Opens the image toolbar.
|
|
236
235
|
const addImageButtonClickHandler = () => {
|
|
237
236
|
editor._tiptapEditor.view.dispatch(
|
|
238
|
-
editor._tiptapEditor.state.tr.setMeta(
|
|
237
|
+
editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {
|
|
239
238
|
block: block,
|
|
240
239
|
})
|
|
241
240
|
);
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Uploads a file to tmpfiles.org and returns the URL to the uploaded file.
|
|
3
|
+
*
|
|
4
|
+
* @warning This function should only be used for development purposes, replace with your own backend!
|
|
5
|
+
*/
|
|
6
|
+
export const uploadToTmpFilesDotOrg_DEV_ONLY = async (
|
|
7
|
+
file: File
|
|
8
|
+
): Promise<string> => {
|
|
2
9
|
const body = new FormData();
|
|
3
10
|
body.append("file", file);
|
|
4
11
|
|
package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers";
|
|
8
8
|
import { defaultProps } from "../../defaultProps";
|
|
9
9
|
import { handleEnter } from "../ListItemKeyboardShortcuts";
|
|
10
|
+
import { getCurrentBlockContentType } from "../../../api/getCurrentBlockContentType";
|
|
10
11
|
|
|
11
12
|
export const bulletListItemPropSchema = {
|
|
12
13
|
...defaultProps,
|
|
@@ -22,6 +23,10 @@ const BulletListItemBlockContent = createStronglyTypedTiptapNode({
|
|
|
22
23
|
new InputRule({
|
|
23
24
|
find: new RegExp(`^[-+*]\\s$`),
|
|
24
25
|
handler: ({ state, chain, range }) => {
|
|
26
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
chain()
|
|
26
31
|
.BNUpdateBlock(state.selection.from, {
|
|
27
32
|
type: "bulletListItem",
|
|
@@ -37,11 +42,19 @@ const BulletListItemBlockContent = createStronglyTypedTiptapNode({
|
|
|
37
42
|
addKeyboardShortcuts() {
|
|
38
43
|
return {
|
|
39
44
|
Enter: () => handleEnter(this.editor),
|
|
40
|
-
"Mod-Shift-8": () =>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
"Mod-Shift-8": () => {
|
|
46
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return this.editor.commands.BNUpdateBlock(
|
|
51
|
+
this.editor.state.selection.anchor,
|
|
52
|
+
{
|
|
53
|
+
type: "bulletListItem",
|
|
54
|
+
props: {},
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
},
|
|
45
58
|
};
|
|
46
59
|
},
|
|
47
60
|
|
|
@@ -10,7 +10,13 @@ export const handleEnter = (editor: Editor) => {
|
|
|
10
10
|
const selectionEmpty =
|
|
11
11
|
editor.state.selection.anchor === editor.state.selection.head;
|
|
12
12
|
|
|
13
|
-
if (
|
|
13
|
+
if (
|
|
14
|
+
!(
|
|
15
|
+
contentType.name === "bulletListItem" ||
|
|
16
|
+
contentType.name === "numberedListItem"
|
|
17
|
+
) ||
|
|
18
|
+
!selectionEmpty
|
|
19
|
+
) {
|
|
14
20
|
return false;
|
|
15
21
|
}
|
|
16
22
|
|
package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers";
|
|
|
8
8
|
import { defaultProps } from "../../defaultProps";
|
|
9
9
|
import { handleEnter } from "../ListItemKeyboardShortcuts";
|
|
10
10
|
import { NumberedListIndexingPlugin } from "./NumberedListIndexingPlugin";
|
|
11
|
+
import { getCurrentBlockContentType } from "../../../api/getCurrentBlockContentType";
|
|
11
12
|
|
|
12
13
|
export const numberedListItemPropSchema = {
|
|
13
14
|
...defaultProps,
|
|
@@ -37,6 +38,10 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
|
|
|
37
38
|
new InputRule({
|
|
38
39
|
find: new RegExp(`^1\\.\\s$`),
|
|
39
40
|
handler: ({ state, chain, range }) => {
|
|
41
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
chain()
|
|
41
46
|
.BNUpdateBlock(state.selection.from, {
|
|
42
47
|
type: "numberedListItem",
|
|
@@ -52,11 +57,19 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
|
|
|
52
57
|
addKeyboardShortcuts() {
|
|
53
58
|
return {
|
|
54
59
|
Enter: () => handleEnter(this.editor),
|
|
55
|
-
"Mod-Shift-7": () =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
"Mod-Shift-7": () => {
|
|
61
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.editor.commands.BNUpdateBlock(
|
|
66
|
+
this.editor.state.selection.anchor,
|
|
67
|
+
{
|
|
68
|
+
type: "numberedListItem",
|
|
69
|
+
props: {},
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
},
|
|
60
73
|
};
|
|
61
74
|
},
|
|
62
75
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers";
|
|
6
6
|
import { defaultProps } from "../defaultProps";
|
|
7
7
|
import { handleEnter } from "../ListItemBlockContent/ListItemKeyboardShortcuts";
|
|
8
|
+
import { getCurrentBlockContentType } from "../../api/getCurrentBlockContentType";
|
|
8
9
|
|
|
9
10
|
export const paragraphPropSchema = {
|
|
10
11
|
...defaultProps,
|
|
@@ -18,11 +19,19 @@ export const ParagraphBlockContent = createStronglyTypedTiptapNode({
|
|
|
18
19
|
addKeyboardShortcuts() {
|
|
19
20
|
return {
|
|
20
21
|
Enter: () => handleEnter(this.editor),
|
|
21
|
-
"Mod-Alt-0": () =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
"Mod-Alt-0": () => {
|
|
23
|
+
if (getCurrentBlockContentType(this.editor) !== "inline*") {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return this.editor.commands.BNUpdateBlock(
|
|
28
|
+
this.editor.state.selection.anchor,
|
|
29
|
+
{
|
|
30
|
+
type: "paragraph",
|
|
31
|
+
props: {},
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
},
|
|
26
35
|
};
|
|
27
36
|
},
|
|
28
37
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { blockToNode } from "../api/nodeConversions/nodeConversions";
|
|
2
2
|
import type { BlockNoteEditor } from "../editor/BlockNoteEditor";
|
|
3
3
|
import type {
|
|
4
|
-
|
|
4
|
+
BlockNoDefaults,
|
|
5
5
|
BlockSchema,
|
|
6
6
|
InlineContentSchema,
|
|
7
7
|
StyleSchema,
|
|
@@ -61,7 +61,7 @@ export const defaultBlockToHTML = <
|
|
|
61
61
|
I extends InlineContentSchema,
|
|
62
62
|
S extends StyleSchema
|
|
63
63
|
>(
|
|
64
|
-
block:
|
|
64
|
+
block: BlockNoDefaults<BSchema, I, S>,
|
|
65
65
|
editor: BlockNoteEditor<BSchema, I, S>
|
|
66
66
|
): {
|
|
67
67
|
dom: HTMLElement;
|
|
@@ -70,7 +70,7 @@ export const defaultBlockToHTML = <
|
|
|
70
70
|
const node = blockToNode(
|
|
71
71
|
block,
|
|
72
72
|
editor._tiptapEditor.schema,
|
|
73
|
-
editor.styleSchema
|
|
73
|
+
editor.schema.styleSchema
|
|
74
74
|
).firstChild!;
|
|
75
75
|
const toDOM = editor._tiptapEditor.schema.nodes[node.type.name].spec.toDOM;
|
|
76
76
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { BlockNoteEditor } from "../editor/BlockNoteEditor";
|
|
2
|
+
import { BlockFromConfig, InlineContentSchema, StyleSchema } from "../schema";
|
|
3
|
+
import { Block, DefaultBlockSchema, defaultBlockSchema } from "./defaultBlocks";
|
|
4
|
+
import { defaultProps } from "./defaultProps";
|
|
5
|
+
|
|
6
|
+
export function checkDefaultBlockTypeInSchema<
|
|
7
|
+
BlockType extends keyof DefaultBlockSchema,
|
|
8
|
+
I extends InlineContentSchema,
|
|
9
|
+
S extends StyleSchema
|
|
10
|
+
>(
|
|
11
|
+
blockType: BlockType,
|
|
12
|
+
editor: BlockNoteEditor<any, I, S>
|
|
13
|
+
): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {
|
|
14
|
+
return (
|
|
15
|
+
blockType in editor.schema.blockSchema &&
|
|
16
|
+
editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function checkBlockIsDefaultType<
|
|
21
|
+
BlockType extends keyof DefaultBlockSchema,
|
|
22
|
+
I extends InlineContentSchema,
|
|
23
|
+
S extends StyleSchema
|
|
24
|
+
>(
|
|
25
|
+
blockType: BlockType,
|
|
26
|
+
block: Block<any, I, S>,
|
|
27
|
+
editor: BlockNoteEditor<any, I, S>
|
|
28
|
+
): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {
|
|
29
|
+
return (
|
|
30
|
+
block.type === blockType &&
|
|
31
|
+
block.type in editor.schema.blockSchema &&
|
|
32
|
+
checkDefaultBlockTypeInSchema(block.type, editor)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function checkBlockTypeHasDefaultProp<
|
|
37
|
+
Prop extends keyof typeof defaultProps,
|
|
38
|
+
I extends InlineContentSchema,
|
|
39
|
+
S extends StyleSchema
|
|
40
|
+
>(
|
|
41
|
+
prop: Prop,
|
|
42
|
+
blockType: string,
|
|
43
|
+
editor: BlockNoteEditor<any, I, S>
|
|
44
|
+
): editor is BlockNoteEditor<
|
|
45
|
+
{
|
|
46
|
+
[BT in string]: {
|
|
47
|
+
type: BT;
|
|
48
|
+
propSchema: {
|
|
49
|
+
[P in Prop]: (typeof defaultProps)[P];
|
|
50
|
+
};
|
|
51
|
+
content: "table" | "inline" | "none";
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
I,
|
|
55
|
+
S
|
|
56
|
+
> {
|
|
57
|
+
return (
|
|
58
|
+
blockType in editor.schema.blockSchema &&
|
|
59
|
+
prop in editor.schema.blockSchema[blockType].propSchema &&
|
|
60
|
+
editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function checkBlockHasDefaultProp<
|
|
65
|
+
Prop extends keyof typeof defaultProps,
|
|
66
|
+
I extends InlineContentSchema,
|
|
67
|
+
S extends StyleSchema
|
|
68
|
+
>(
|
|
69
|
+
prop: Prop,
|
|
70
|
+
block: Block<any, I, S>,
|
|
71
|
+
editor: BlockNoteEditor<any, I, S>
|
|
72
|
+
): block is BlockFromConfig<
|
|
73
|
+
{
|
|
74
|
+
type: string;
|
|
75
|
+
propSchema: {
|
|
76
|
+
[P in Prop]: (typeof defaultProps)[P];
|
|
77
|
+
};
|
|
78
|
+
content: "table" | "inline" | "none";
|
|
79
|
+
},
|
|
80
|
+
I,
|
|
81
|
+
S
|
|
82
|
+
> {
|
|
83
|
+
return checkBlockTypeHasDefaultProp(prop, block.type, editor);
|
|
84
|
+
}
|