UNPKG

@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
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, }; }, });