UNPKG

@blocknote/core

Version:

A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.

97 lines (89 loc) 2.4 kB
import { Attributes, Mark } from "@tiptap/core"; import { StyleConfig, StyleImplementation, StylePropSchema, StyleSchemaFromSpecs, StyleSpec, StyleSpecs, } from "./types.js"; export function stylePropsToAttributes( propSchema: StylePropSchema, ): Attributes { if (propSchema === "boolean") { return {}; } return { stringValue: { default: undefined, keepOnSplit: true, parseHTML: (element) => element.getAttribute("data-value"), renderHTML: (attributes) => attributes.stringValue !== undefined ? { "data-value": attributes.stringValue, } : {}, }, }; } // Function that adds necessary classes and attributes to the `dom` element // returned from a custom style's 'render' function, to ensure no data is lost // on internal copy & paste. export function addStyleAttributes< SType extends string, PSchema extends StylePropSchema, >( element: { dom: HTMLElement; contentDOM?: HTMLElement; }, styleType: SType, styleValue: PSchema extends "boolean" ? undefined : string, propSchema: PSchema, ): { dom: HTMLElement; contentDOM?: HTMLElement; } { // Sets content type attribute element.dom.setAttribute("data-style-type", styleType); // Adds style value as an HTML attribute in kebab-case with "data-" prefix, if // the style takes a string value. if (propSchema === "string") { element.dom.setAttribute("data-value", styleValue as string); } if (element.contentDOM !== undefined) { element.contentDOM.setAttribute("data-editable", ""); } return element; } // This helper function helps to instantiate a stylespec with a // config and implementation that conform to the type of Config export function createInternalStyleSpec<T extends StyleConfig>( config: T, implementation: StyleImplementation, ) { return { config, implementation, } satisfies StyleSpec<T>; } export function createStyleSpecFromTipTapMark< T extends Mark, P extends StylePropSchema, >(mark: T, propSchema: P) { return createInternalStyleSpec( { type: mark.name as T["name"], propSchema, }, { mark, }, ); } export function getStyleSchemaFromSpecs<T extends StyleSpecs>(specs: T) { return Object.fromEntries( Object.entries(specs).map(([key, value]) => [key, value.config]), ) as StyleSchemaFromSpecs<T>; }