@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
89 lines (79 loc) • 2.66 kB
text/typescript
import { Node } from "@tiptap/core";
import type { BlockNoteEditor } from "../editor/BlockNoteEditor.js";
import { BlockNoteDOMAttributes } from "../schema/index.js";
import { mergeCSSClasses } from "../util/browser.js";
// Object containing all possible block attributes.
const BlockAttributes: Record<string, string> = {
blockColor: "data-block-color",
blockStyle: "data-block-style",
id: "data-id",
depth: "data-depth",
depthChange: "data-depth-change",
};
/**
* The main "Block node" documents consist of
*/
export const BlockContainer = Node.create<{
domAttributes?: BlockNoteDOMAttributes;
editor: BlockNoteEditor<any, any, any>;
}>({
name: "blockContainer",
group: "blockGroupChild bnBlock",
// A block always contains content, and optionally a blockGroup which contains nested blocks
content: "blockContent blockGroup?",
// Ensures content-specific keyboard handlers trigger first.
priority: 50,
defining: true,
marks: "insertion modification deletion",
parseHTML() {
return [
{
tag: "div[data-node-type=" + this.name + "]",
getAttrs: (element) => {
if (typeof element === "string") {
return false;
}
const attrs: Record<string, string> = {};
for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {
if (element.getAttribute(HTMLAttr)) {
attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;
}
}
return attrs;
},
},
// Ignore `blockOuter` divs, but parse the `blockContainer` divs inside them.
{
tag: `div[data-node-type="blockOuter"]`,
skip: true,
},
];
},
renderHTML({ HTMLAttributes }) {
const blockOuter = document.createElement("div");
blockOuter.className = "bn-block-outer";
blockOuter.setAttribute("data-node-type", "blockOuter");
for (const [attribute, value] of Object.entries(HTMLAttributes)) {
if (attribute !== "class") {
blockOuter.setAttribute(attribute, value);
}
}
const blockHTMLAttributes = {
...(this.options.domAttributes?.block || {}),
...HTMLAttributes,
};
const block = document.createElement("div");
block.className = mergeCSSClasses("bn-block", blockHTMLAttributes.class);
block.setAttribute("data-node-type", this.name);
for (const [attribute, value] of Object.entries(blockHTMLAttributes)) {
if (attribute !== "class") {
block.setAttribute(attribute, value);
}
}
blockOuter.appendChild(block);
return {
dom: blockOuter,
contentDOM: block,
};
},
});