@blocknote/core
Advanced tools
Comparing version 0.10.1 to 0.11.0
@@ -1,1 +0,1 @@ | ||
{"builtAt":1701996536387,"assets":[{"name":"blocknote.umd.cjs","size":99157},{"name":"blocknote.umd.cjs.map","size":445605}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8518,"chunks":["a1ee98a"]},{"name":"./src/api/getBlockInfoFromPos.ts","size":1691,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/types.ts","size":302,"chunks":["a1ee98a"]},{"name":"./src/util/typescript.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/nodeConversions.ts","size":11959,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/sharedHTMLConversion.ts","size":2272,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","size":2687,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":1059,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":697,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":432,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1724,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":3701,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":2781,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1357,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":1613,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":2796,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/ImageToolbar/ImageToolbarPlugin.ts","size":3772,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":9242,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1106,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":2691,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":1862,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":3148,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":753,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":1462,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":1207,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1025,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":548,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/blockManipulation.ts","size":2541,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":549,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/util/nestedLists.ts","size":2022,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/parseHTML.ts","size":503,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/markdown/parseMarkdown.ts","size":1054,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":4866,"chunks":["a1ee98a"]},{"name":"./src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","size":7599,"chunks":["a1ee98a"]},{"name":"./src/extensions-shared/suggestion/SuggestionPlugin.ts","size":9492,"chunks":["a1ee98a"]},{"name":"./src/extensions/SlashMenu/SlashMenuPlugin.ts","size":839,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":15162,"chunks":["a1ee98a"]},{"name":"./src/extensions/SlashMenu/defaultSlashMenuItems.ts","size":4114,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":14650,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/copyExtension.ts","size":1406,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/pasteExtension.ts","size":1168,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":688,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderExtension.ts","size":2106,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":748,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":622,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1594,"chunks":["a1ee98a"]},{"name":"./src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","size":341,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4572,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":17257,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockGroup.ts","size":1097,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/Doc.ts","size":90,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteExtensions.ts","size":3467,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":1017,"chunks":["a1ee98a"]},{"name":"./src/editor/Block.css","size":17,"chunks":["a1ee98a"]},{"name":"./src/editor/editor.css","size":18,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":22030,"chunks":["a1ee98a"]},{"name":"./src/api/testUtil/partialBlockTestUtil.ts","size":2166,"chunks":["a1ee98a"]},{"name":"./src/index.ts","size":0,"chunks":["a1ee98a"]}]} | ||
{"builtAt":1704762819220,"assets":[{"name":"blocknote.umd.cjs","size":100567},{"name":"blocknote.umd.cjs.map","size":453755}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8518,"chunks":["a1ee98a"]},{"name":"./src/api/getBlockInfoFromPos.ts","size":1691,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/types.ts","size":302,"chunks":["a1ee98a"]},{"name":"./src/util/typescript.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/nodeConversions.ts","size":11959,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/sharedHTMLConversion.ts","size":2272,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","size":2687,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":1059,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":697,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":432,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1724,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":3701,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":2781,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1357,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":1613,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":2796,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/ImageToolbar/ImageToolbarPlugin.ts","size":3772,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":9011,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1106,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":2691,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":1862,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":3148,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":753,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":1462,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":1207,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1025,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":548,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/blockManipulation.ts","size":4471,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":549,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/util/nestedLists.ts","size":2022,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/parseHTML.ts","size":503,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/markdown/parseMarkdown.ts","size":1054,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":4866,"chunks":["a1ee98a"]},{"name":"./src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","size":7599,"chunks":["a1ee98a"]},{"name":"./src/extensions-shared/suggestion/SuggestionPlugin.ts","size":9492,"chunks":["a1ee98a"]},{"name":"./src/extensions/SlashMenu/SlashMenuPlugin.ts","size":839,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":15178,"chunks":["a1ee98a"]},{"name":"./src/extensions/SlashMenu/defaultSlashMenuItems.ts","size":4114,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":14723,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/copyExtension.ts","size":2883,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/pasteExtension.ts","size":1131,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":688,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderExtension.ts","size":2106,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":748,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":622,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1594,"chunks":["a1ee98a"]},{"name":"./src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","size":467,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4572,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":17340,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockGroup.ts","size":1097,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/Doc.ts","size":90,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteExtensions.ts","size":3467,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":1017,"chunks":["a1ee98a"]},{"name":"./src/editor/Block.css","size":17,"chunks":["a1ee98a"]},{"name":"./src/editor/editor.css","size":18,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":22030,"chunks":["a1ee98a"]},{"name":"./src/api/testUtil/partialBlockTestUtil.ts","size":2166,"chunks":["a1ee98a"]},{"name":"./src/index.ts","size":0,"chunks":["a1ee98a"]}]} |
@@ -6,3 +6,3 @@ { | ||
"license": "MPL-2.0", | ||
"version": "0.10.1", | ||
"version": "0.11.0", | ||
"files": [ | ||
@@ -119,3 +119,3 @@ "dist", | ||
}, | ||
"gitHead": "a6a938948a6e94273c2ec4d23371d10406c99bcc" | ||
"gitHead": "db565110840b367d5e5220fdc790c5e7b476ff5b" | ||
} |
@@ -38,3 +38,3 @@ <p align="center"> | ||
import { BlockNoteView, useBlockNote } from "@blocknote/react"; | ||
import "@blocknote/core/style.css"; | ||
import "@blocknote/react/style.css"; | ||
@@ -41,0 +41,0 @@ function App() { |
@@ -1,2 +0,1 @@ | ||
import { Editor } from "@tiptap/core"; | ||
import { Node } from "prosemirror-model"; | ||
@@ -6,2 +5,3 @@ | ||
import { | ||
Block, | ||
BlockIdentifier, | ||
@@ -13,4 +13,5 @@ BlockSchema, | ||
} from "../../schema"; | ||
import { blockToNode } from "../nodeConversions/nodeConversions"; | ||
import { blockToNode, nodeToBlock } from "../nodeConversions/nodeConversions"; | ||
import { getNodeById } from "../nodeUtil"; | ||
import { Transaction } from "prosemirror-state"; | ||
@@ -26,3 +27,3 @@ export function insertBlocks< | ||
editor: BlockNoteEditor<BSchema, I, S> | ||
): void { | ||
): Block<BSchema, I, S>[] { | ||
const ttEditor = editor._tiptapEditor; | ||
@@ -40,12 +41,14 @@ | ||
let insertionPos = -1; | ||
const { node, posBeforeNode } = getNodeById(id, ttEditor.state.doc); | ||
if (placement === "before") { | ||
insertionPos = posBeforeNode; | ||
ttEditor.view.dispatch( | ||
ttEditor.state.tr.insert(posBeforeNode, nodesToInsert) | ||
); | ||
} | ||
if (placement === "after") { | ||
insertionPos = posBeforeNode + node.nodeSize; | ||
ttEditor.view.dispatch( | ||
ttEditor.state.tr.insert(posBeforeNode + node.nodeSize, nodesToInsert) | ||
); | ||
} | ||
@@ -56,4 +59,2 @@ | ||
if (node.childCount < 2) { | ||
insertionPos = posBeforeNode + node.firstChild!.nodeSize + 1; | ||
const blockGroupNode = ttEditor.state.schema.nodes["blockGroup"].create( | ||
@@ -65,12 +66,26 @@ {}, | ||
ttEditor.view.dispatch( | ||
ttEditor.state.tr.insert(insertionPos, blockGroupNode) | ||
ttEditor.state.tr.insert( | ||
posBeforeNode + node.firstChild!.nodeSize + 1, | ||
blockGroupNode | ||
) | ||
); | ||
return; | ||
} | ||
} | ||
insertionPos = posBeforeNode + node.firstChild!.nodeSize + 2; | ||
// Now that the `PartialBlock`s have been converted to nodes, we can | ||
// re-convert them into full `Block`s. | ||
const insertedBlocks: Block<BSchema, I, S>[] = []; | ||
for (const node of nodesToInsert) { | ||
insertedBlocks.push( | ||
nodeToBlock( | ||
node, | ||
editor.blockSchema, | ||
editor.inlineContentSchema, | ||
editor.styleSchema, | ||
editor.blockCache | ||
) | ||
); | ||
} | ||
ttEditor.view.dispatch(ttEditor.state.tr.insert(insertionPos, nodesToInsert)); | ||
return insertedBlocks; | ||
} | ||
@@ -85,15 +100,43 @@ | ||
update: PartialBlock<BSchema, I, S>, | ||
editor: Editor | ||
) { | ||
editor: BlockNoteEditor<BSchema, I, S> | ||
): Block<BSchema, I, S> { | ||
const ttEditor = editor._tiptapEditor; | ||
const id = | ||
typeof blockToUpdate === "string" ? blockToUpdate : blockToUpdate.id; | ||
const { posBeforeNode } = getNodeById(id, editor.state.doc); | ||
const { posBeforeNode } = getNodeById(id, ttEditor.state.doc); | ||
editor.commands.BNUpdateBlock(posBeforeNode + 1, update); | ||
ttEditor.commands.BNUpdateBlock(posBeforeNode + 1, update); | ||
const blockContainerNode = ttEditor.state.doc | ||
.resolve(posBeforeNode + 1) | ||
.node(); | ||
return nodeToBlock( | ||
blockContainerNode, | ||
editor.blockSchema, | ||
editor.inlineContentSchema, | ||
editor.styleSchema, | ||
editor.blockCache | ||
); | ||
} | ||
export function removeBlocks( | ||
function removeBlocksWithCallback< | ||
BSchema extends BlockSchema, | ||
I extends InlineContentSchema, | ||
S extends StyleSchema | ||
>( | ||
blocksToRemove: BlockIdentifier[], | ||
editor: Editor | ||
) { | ||
editor: BlockNoteEditor<BSchema, I, S>, | ||
// Should return new removedSize. | ||
callback?: ( | ||
node: Node, | ||
pos: number, | ||
tr: Transaction, | ||
removedSize: number | ||
) => number | ||
): Block<BSchema, I, S>[] { | ||
const ttEditor = editor._tiptapEditor; | ||
const tr = ttEditor.state.tr; | ||
const idsOfBlocksToRemove = new Set<string>( | ||
@@ -104,6 +147,6 @@ blocksToRemove.map((block) => | ||
); | ||
const removedBlocks: Block<BSchema, I, S>[] = []; | ||
let removedSize = 0; | ||
editor.state.doc.descendants((node, pos) => { | ||
ttEditor.state.doc.descendants((node, pos) => { | ||
// Skips traversing nodes after all target blocks have been removed. | ||
@@ -122,8 +165,19 @@ if (idsOfBlocksToRemove.size === 0) { | ||
// Saves the block that is being deleted. | ||
removedBlocks.push( | ||
nodeToBlock( | ||
node, | ||
editor.blockSchema, | ||
editor.inlineContentSchema, | ||
editor.styleSchema, | ||
editor.blockCache | ||
) | ||
); | ||
idsOfBlocksToRemove.delete(node.attrs.id); | ||
const oldDocSize = editor.state.doc.nodeSize; | ||
editor.commands.BNDeleteBlock(pos - removedSize + 1); | ||
const newDocSize = editor.state.doc.nodeSize; | ||
// Removes the block and calculates the change in document size. | ||
removedSize = callback?.(node, pos, tr, removedSize) || removedSize; | ||
const oldDocSize = tr.doc.nodeSize; | ||
tr.delete(pos - removedSize - 1, pos - removedSize + node.nodeSize + 1); | ||
const newDocSize = tr.doc.nodeSize; | ||
removedSize += oldDocSize - newDocSize; | ||
@@ -134,2 +188,3 @@ | ||
// Throws an error if now all blocks could be found. | ||
if (idsOfBlocksToRemove.size > 0) { | ||
@@ -143,4 +198,19 @@ const notFoundIds = [...idsOfBlocksToRemove].join("\n"); | ||
} | ||
ttEditor.view.dispatch(tr); | ||
return removedBlocks; | ||
} | ||
export function removeBlocks< | ||
BSchema extends BlockSchema, | ||
I extends InlineContentSchema, | ||
S extends StyleSchema | ||
>( | ||
blocksToRemove: BlockIdentifier[], | ||
editor: BlockNoteEditor<BSchema, I, S> | ||
): Block<BSchema, I, S>[] { | ||
return removeBlocksWithCallback(blocksToRemove, editor); | ||
} | ||
export function replaceBlocks< | ||
@@ -154,5 +224,49 @@ BSchema extends BlockSchema, | ||
editor: BlockNoteEditor<BSchema, I, S> | ||
) { | ||
insertBlocks(blocksToInsert, blocksToRemove[0], "before", editor); | ||
removeBlocks(blocksToRemove, editor._tiptapEditor); | ||
): { | ||
insertedBlocks: Block<BSchema, I, S>[]; | ||
removedBlocks: Block<BSchema, I, S>[]; | ||
} { | ||
const ttEditor = editor._tiptapEditor; | ||
const nodesToInsert: Node[] = []; | ||
for (const block of blocksToInsert) { | ||
nodesToInsert.push(blockToNode(block, ttEditor.schema, editor.styleSchema)); | ||
} | ||
const idOfFirstBlock = | ||
typeof blocksToRemove[0] === "string" | ||
? blocksToRemove[0] | ||
: blocksToRemove[0].id; | ||
const removedBlocks = removeBlocksWithCallback( | ||
blocksToRemove, | ||
editor, | ||
(node, pos, tr, removedSize) => { | ||
if (node.attrs.id === idOfFirstBlock) { | ||
const oldDocSize = tr.doc.nodeSize; | ||
tr.insert(pos, nodesToInsert); | ||
const newDocSize = tr.doc.nodeSize; | ||
return removedSize + oldDocSize - newDocSize; | ||
} | ||
return removedSize; | ||
} | ||
); | ||
// Now that the `PartialBlock`s have been converted to nodes, we can | ||
// re-convert them into full `Block`s. | ||
const insertedBlocks: Block<BSchema, I, S>[] = []; | ||
for (const node of nodesToInsert) { | ||
insertedBlocks.push( | ||
nodeToBlock( | ||
node, | ||
editor.blockSchema, | ||
editor.inlineContentSchema, | ||
editor.styleSchema, | ||
editor.blockCache | ||
) | ||
); | ||
} | ||
return { insertedBlocks, removedBlocks }; | ||
} |
import { Extension } from "@tiptap/core"; | ||
import { Plugin } from "prosemirror-state"; | ||
import { NodeSelection, Plugin } from "prosemirror-state"; | ||
import { Node } from "prosemirror-model"; | ||
@@ -9,3 +10,37 @@ import type { BlockNoteEditor } from "../../editor/BlockNoteEditor"; | ||
import { cleanHTMLToMarkdown } from "./markdown/markdownExporter"; | ||
import { EditorView } from "prosemirror-view"; | ||
function selectedFragmentToHTML< | ||
BSchema extends BlockSchema, | ||
I extends InlineContentSchema, | ||
S extends StyleSchema | ||
>( | ||
view: EditorView, | ||
editor: BlockNoteEditor<BSchema, I, S> | ||
): { | ||
internalHTML: string; | ||
externalHTML: string; | ||
plainText: string; | ||
} { | ||
const selectedFragment = view.state.selection.content().content; | ||
const internalHTMLSerializer = createInternalHTMLSerializer( | ||
view.state.schema, | ||
editor | ||
); | ||
const internalHTML = | ||
internalHTMLSerializer.serializeProseMirrorFragment(selectedFragment); | ||
const externalHTMLExporter = createExternalHTMLExporter( | ||
view.state.schema, | ||
editor | ||
); | ||
const externalHTML = | ||
externalHTMLExporter.exportProseMirrorFragment(selectedFragment); | ||
const plainText = cleanHTMLToMarkdown(externalHTML); | ||
return { internalHTML, externalHTML, plainText }; | ||
} | ||
export const createCopyToClipboardExtension = < | ||
@@ -21,4 +56,2 @@ BSchema extends BlockSchema, | ||
addProseMirrorPlugins() { | ||
const tiptap = this.editor; | ||
const schema = this.editor.schema; | ||
return [ | ||
@@ -28,3 +61,3 @@ new Plugin({ | ||
handleDOMEvents: { | ||
copy(_view, event) { | ||
copy(view, event) { | ||
// Stops the default browser copy behaviour. | ||
@@ -34,25 +67,23 @@ event.preventDefault(); | ||
const selectedFragment = | ||
tiptap.state.selection.content().content; | ||
const internalHTMLSerializer = createInternalHTMLSerializer( | ||
schema, | ||
editor | ||
); | ||
const internalHTML = | ||
internalHTMLSerializer.serializeProseMirrorFragment( | ||
selectedFragment | ||
// Checks if a `blockContent` node is being copied and expands | ||
// the selection to the parent `blockContainer` node. This is | ||
// for the use-case in which only a block without content is | ||
// selected, e.g. an image block. | ||
if ( | ||
"node" in view.state.selection && | ||
(view.state.selection.node as Node).type.spec.group === | ||
"blockContent" | ||
) { | ||
view.dispatch( | ||
view.state.tr.setSelection( | ||
new NodeSelection( | ||
view.state.doc.resolve(view.state.selection.from - 1) | ||
) | ||
) | ||
); | ||
} | ||
const externalHTMLExporter = createExternalHTMLExporter( | ||
schema, | ||
editor | ||
); | ||
const externalHTML = | ||
externalHTMLExporter.exportProseMirrorFragment( | ||
selectedFragment | ||
); | ||
const { internalHTML, externalHTML, plainText } = | ||
selectedFragmentToHTML(view, editor); | ||
const plainText = cleanHTMLToMarkdown(externalHTML); | ||
// TODO: Writing to other MIME types not working in Safari for | ||
@@ -67,2 +98,44 @@ // some reason. | ||
}, | ||
// This is for the use-case in which only a block without content | ||
// is selected, e.g. an image block, and dragged (not using the | ||
// drag handle). | ||
dragstart(view, event) { | ||
// Checks if a `NodeSelection` is active. | ||
if (!("node" in view.state.selection)) { | ||
return; | ||
} | ||
// Checks if a `blockContent` node is being dragged. | ||
if ( | ||
(view.state.selection.node as Node).type.spec.group !== | ||
"blockContent" | ||
) { | ||
return; | ||
} | ||
// Expands the selection to the parent `blockContainer` node. | ||
view.dispatch( | ||
view.state.tr.setSelection( | ||
new NodeSelection( | ||
view.state.doc.resolve(view.state.selection.from - 1) | ||
) | ||
) | ||
); | ||
// Stops the default browser drag start behaviour. | ||
event.preventDefault(); | ||
event.dataTransfer!.clearData(); | ||
const { internalHTML, externalHTML, plainText } = | ||
selectedFragmentToHTML(view, editor); | ||
// TODO: Writing to other MIME types not working in Safari for | ||
// some reason. | ||
event.dataTransfer!.setData("blocknote/html", internalHTML); | ||
event.dataTransfer!.setData("text/html", externalHTML); | ||
event.dataTransfer!.setData("text/plain", plainText); | ||
// Prevent default PM handler to be called | ||
return true; | ||
}, | ||
}, | ||
@@ -69,0 +142,0 @@ }, |
@@ -35,2 +35,3 @@ import { DOMSerializer, Fragment, Node } from "prosemirror-model"; | ||
} | ||
const { dom, contentDOM } = DOMSerializer.renderSpec( | ||
@@ -37,0 +38,0 @@ doc(options), |
@@ -47,3 +47,2 @@ import { Extension } from "@tiptap/core"; | ||
data = htmlNode.innerHTML; | ||
console.log(data); | ||
} | ||
@@ -50,0 +49,0 @@ editor._tiptapEditor.view.pasteHTML(data); |
@@ -72,3 +72,2 @@ import type { BlockNoteEditor } from "../../editor/BlockNoteEditor"; | ||
addImageButton.className = "bn-add-image-button"; | ||
addImageButton.style.display = block.props.url === "" ? "" : "none"; | ||
@@ -87,3 +86,2 @@ // Icon for the add image button. | ||
imageAndCaptionWrapper.className = "bn-image-and-caption-wrapper"; | ||
imageAndCaptionWrapper.style.display = block.props.url !== "" ? "" : "none"; | ||
@@ -93,3 +91,2 @@ // Wrapper element for the image and resize handles. | ||
imageWrapper.className = "bn-image-wrapper"; | ||
imageWrapper.style.display = block.props.url !== "" ? "" : "none"; | ||
@@ -211,4 +208,4 @@ // Image element. | ||
) { | ||
leftResizeHandle.style.display = "none"; | ||
rightResizeHandle.style.display = "none"; | ||
imageWrapper.removeChild(leftResizeHandle); | ||
imageWrapper.removeChild(rightResizeHandle); | ||
} | ||
@@ -243,7 +240,7 @@ | ||
if (editor.isEditable) { | ||
leftResizeHandle.style.display = "block"; | ||
rightResizeHandle.style.display = "block"; | ||
imageWrapper.appendChild(leftResizeHandle); | ||
imageWrapper.appendChild(rightResizeHandle); | ||
} else { | ||
leftResizeHandle.style.display = "none"; | ||
rightResizeHandle.style.display = "none"; | ||
imageWrapper.removeChild(leftResizeHandle); | ||
imageWrapper.removeChild(rightResizeHandle); | ||
} | ||
@@ -265,4 +262,4 @@ }; | ||
leftResizeHandle.style.display = "none"; | ||
rightResizeHandle.style.display = "none"; | ||
imageWrapper.removeChild(leftResizeHandle); | ||
imageWrapper.removeChild(rightResizeHandle); | ||
}; | ||
@@ -275,4 +272,4 @@ | ||
leftResizeHandle.style.display = "block"; | ||
rightResizeHandle.style.display = "block"; | ||
imageWrapper.appendChild(leftResizeHandle); | ||
imageWrapper.appendChild(rightResizeHandle); | ||
@@ -288,4 +285,4 @@ resizeParams = { | ||
leftResizeHandle.style.display = "block"; | ||
rightResizeHandle.style.display = "block"; | ||
imageWrapper.appendChild(leftResizeHandle); | ||
imageWrapper.appendChild(rightResizeHandle); | ||
@@ -299,12 +296,15 @@ resizeParams = { | ||
wrapper.appendChild(addImageButton); | ||
addImageButton.appendChild(addImageButtonIcon); | ||
addImageButton.appendChild(addImageButtonText); | ||
wrapper.appendChild(imageAndCaptionWrapper); | ||
imageAndCaptionWrapper.appendChild(imageWrapper); | ||
imageWrapper.appendChild(image); | ||
imageWrapper.appendChild(leftResizeHandle); | ||
imageWrapper.appendChild(rightResizeHandle); | ||
imageAndCaptionWrapper.appendChild(caption); | ||
if (block.props.url === "") { | ||
wrapper.appendChild(addImageButton); | ||
} else { | ||
wrapper.appendChild(imageAndCaptionWrapper); | ||
} | ||
window.addEventListener("mousemove", windowMouseMoveHandler); | ||
@@ -311,0 +311,0 @@ window.addEventListener("mouseup", windowMouseUpHandler); |
@@ -24,7 +24,7 @@ import { Editor, EditorOptions, Extension } from "@tiptap/core"; | ||
DefaultBlockSchema, | ||
DefaultInlineContentSchema, | ||
DefaultStyleSchema, | ||
defaultBlockSchema, | ||
defaultBlockSpecs, | ||
DefaultInlineContentSchema, | ||
defaultInlineContentSpecs, | ||
DefaultStyleSchema, | ||
defaultStyleSpecs, | ||
@@ -49,2 +49,5 @@ } from "../blocks/defaultBlocks"; | ||
BlockSpecs, | ||
getBlockSchemaFromSpecs, | ||
getInlineContentSchemaFromSpecs, | ||
getStyleSchemaFromSpecs, | ||
InlineContentSchema, | ||
@@ -54,9 +57,6 @@ InlineContentSchemaFromSpecs, | ||
PartialBlock, | ||
Styles, | ||
StyleSchema, | ||
StyleSchemaFromSpecs, | ||
StyleSpecs, | ||
Styles, | ||
getBlockSchemaFromSpecs, | ||
getInlineContentSchemaFromSpecs, | ||
getStyleSchemaFromSpecs, | ||
} from "../schema"; | ||
@@ -781,4 +781,4 @@ import { mergeCSSClasses } from "../util/browser"; | ||
placement: "before" | "after" | "nested" = "before" | ||
): void { | ||
insertBlocks(blocksToInsert, referenceBlock, placement, this); | ||
) { | ||
return insertBlocks(blocksToInsert, referenceBlock, placement, this); | ||
} | ||
@@ -797,3 +797,3 @@ | ||
) { | ||
updateBlock(blockToUpdate, update, this._tiptapEditor); | ||
return updateBlock(blockToUpdate, update, this); | ||
} | ||
@@ -806,3 +806,3 @@ | ||
public removeBlocks(blocksToRemove: BlockIdentifier[]) { | ||
removeBlocks(blocksToRemove, this._tiptapEditor); | ||
return removeBlocks(blocksToRemove, this); | ||
} | ||
@@ -821,3 +821,3 @@ | ||
) { | ||
replaceBlocks(blocksToRemove, blocksToInsert, this); | ||
return replaceBlocks(blocksToRemove, blocksToInsert, this); | ||
} | ||
@@ -824,0 +824,0 @@ |
@@ -11,4 +11,15 @@ import { Plugin, PluginKey } from "prosemirror-state"; | ||
handleKeyDown: (view, event) => { | ||
// Checks for node selection | ||
if ("node" in view.state.selection) { | ||
event.preventDefault(); | ||
// Checks if key input will insert a character - we want to block this | ||
// as it will convert the block into a paragraph. | ||
if ( | ||
event.key.length === 1 && | ||
!event.ctrlKey && | ||
!event.altKey && | ||
!event.metaKey && | ||
!event.shiftKey | ||
) { | ||
event.preventDefault(); | ||
} | ||
} | ||
@@ -15,0 +26,0 @@ }, |
@@ -550,3 +550,3 @@ import { PluginView } from "@tiptap/pm/state"; | ||
const { contentNode, endPos } = blockInfo; | ||
const { contentNode, startPos, endPos } = blockInfo; | ||
@@ -565,3 +565,3 @@ // Creates a new block if current one is not empty for the suggestion menu to open in. | ||
} else { | ||
this.editor._tiptapEditor.commands.setTextSelection(endPos); | ||
this.editor._tiptapEditor.commands.setTextSelection(startPos + 1); | ||
} | ||
@@ -568,0 +568,0 @@ |
@@ -27,3 +27,5 @@ import { Plugin, PluginKey, PluginView } from "prosemirror-state"; | ||
dragImageElement.innerHTML = "_"; | ||
dragImageElement.style.visibility = "hidden"; | ||
dragImageElement.style.opacity = "0"; | ||
dragImageElement.style.height = "1px"; | ||
dragImageElement.style.width = "1px"; | ||
document.body.appendChild(dragImageElement); | ||
@@ -30,0 +32,0 @@ } |
@@ -570,3 +570,3 @@ import { Node } from "@tiptap/core"; | ||
const blockAtDocEnd = false; | ||
const blockAtDocEnd = endPos === state.doc.nodeSize - 4; | ||
const selectionAtBlockEnd = state.selection.from === endPos - 1; | ||
@@ -573,0 +573,0 @@ const selectionEmpty = state.selection.empty; |
@@ -1,7 +0,9 @@ | ||
import { Editor } from "@tiptap/core"; | ||
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor"; | ||
import { BlockIdentifier, BlockSchema, InlineContentSchema, PartialBlock, StyleSchema } from "../../schema"; | ||
export declare function insertBlocks<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blocksToInsert: PartialBlock<BSchema, I, S>[], referenceBlock: BlockIdentifier, placement: "before" | "after" | "nested" | undefined, editor: BlockNoteEditor<BSchema, I, S>): void; | ||
export declare function updateBlock<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blockToUpdate: BlockIdentifier, update: PartialBlock<BSchema, I, S>, editor: Editor): void; | ||
export declare function removeBlocks(blocksToRemove: BlockIdentifier[], editor: Editor): void; | ||
export declare function replaceBlocks<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock<BSchema, I, S>[], editor: BlockNoteEditor<BSchema, I, S>): void; | ||
import { Block, BlockIdentifier, BlockSchema, InlineContentSchema, PartialBlock, StyleSchema } from "../../schema"; | ||
export declare function insertBlocks<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blocksToInsert: PartialBlock<BSchema, I, S>[], referenceBlock: BlockIdentifier, placement: "before" | "after" | "nested" | undefined, editor: BlockNoteEditor<BSchema, I, S>): Block<BSchema, I, S>[]; | ||
export declare function updateBlock<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blockToUpdate: BlockIdentifier, update: PartialBlock<BSchema, I, S>, editor: BlockNoteEditor<BSchema, I, S>): Block<BSchema, I, S>; | ||
export declare function removeBlocks<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blocksToRemove: BlockIdentifier[], editor: BlockNoteEditor<BSchema, I, S>): Block<BSchema, I, S>[]; | ||
export declare function replaceBlocks<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock<BSchema, I, S>[], editor: BlockNoteEditor<BSchema, I, S>): { | ||
insertedBlocks: Block<BSchema, I, S>[]; | ||
removedBlocks: Block<BSchema, I, S>[]; | ||
}; |
@@ -5,3 +5,3 @@ import { EditorOptions } from "@tiptap/core"; | ||
import * as Y from "yjs"; | ||
import { DefaultBlockSchema, DefaultInlineContentSchema, DefaultStyleSchema, defaultBlockSpecs, defaultInlineContentSpecs, defaultStyleSpecs } from "../blocks/defaultBlocks"; | ||
import { DefaultBlockSchema, defaultBlockSpecs, DefaultInlineContentSchema, defaultInlineContentSpecs, DefaultStyleSchema, defaultStyleSpecs } from "../blocks/defaultBlocks"; | ||
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin"; | ||
@@ -14,3 +14,3 @@ import { HyperlinkToolbarProsemirrorPlugin } from "../extensions/HyperlinkToolbar/HyperlinkToolbarPlugin"; | ||
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin"; | ||
import { Block, BlockIdentifier, BlockNoteDOMAttributes, BlockSchema, BlockSchemaFromSpecs, BlockSchemaWithBlock, BlockSpecs, InlineContentSchema, InlineContentSchemaFromSpecs, InlineContentSpecs, PartialBlock, StyleSchema, StyleSchemaFromSpecs, StyleSpecs, Styles } from "../schema"; | ||
import { Block, BlockIdentifier, BlockNoteDOMAttributes, BlockSchema, BlockSchemaFromSpecs, BlockSchemaWithBlock, BlockSpecs, InlineContentSchema, InlineContentSchemaFromSpecs, InlineContentSpecs, PartialBlock, Styles, StyleSchema, StyleSchemaFromSpecs, StyleSpecs } from "../schema"; | ||
import { TextCursorPosition } from "./cursorPositionTypes"; | ||
@@ -192,3 +192,3 @@ import { Selection } from "./selectionTypes"; | ||
*/ | ||
insertBlocks(blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[], referenceBlock: BlockIdentifier, placement?: "before" | "after" | "nested"): void; | ||
insertBlocks(blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[], referenceBlock: BlockIdentifier, placement?: "before" | "after" | "nested"): Block<BSchema, ISchema, SSchema>[]; | ||
/** | ||
@@ -201,3 +201,3 @@ * Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be | ||
*/ | ||
updateBlock(blockToUpdate: BlockIdentifier, update: PartialBlock<BSchema, ISchema, SSchema>): void; | ||
updateBlock(blockToUpdate: BlockIdentifier, update: PartialBlock<BSchema, ISchema, SSchema>): Block<BSchema, ISchema, SSchema>; | ||
/** | ||
@@ -207,3 +207,3 @@ * Removes existing blocks from the editor. Throws an error if any of the blocks could not be found. | ||
*/ | ||
removeBlocks(blocksToRemove: BlockIdentifier[]): void; | ||
removeBlocks(blocksToRemove: BlockIdentifier[]): Block<BSchema, ISchema, SSchema>[]; | ||
/** | ||
@@ -216,3 +216,6 @@ * Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or | ||
*/ | ||
replaceBlocks(blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[]): void; | ||
replaceBlocks(blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[]): { | ||
insertedBlocks: Block<BSchema, ISchema, SSchema>[]; | ||
removedBlocks: Block<BSchema, ISchema, SSchema>[]; | ||
}; | ||
/** | ||
@@ -219,0 +222,0 @@ * Gets the active text styles at the text cursor position or at the end of the current selection if it's active. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2811472
25948