diff --git a/examples/03-ui-components/13-custom-ui/src/MUIFormattingToolbar.tsx b/examples/03-ui-components/13-custom-ui/src/MUIFormattingToolbar.tsx index 69446e9c1a..21d2003d73 100644 --- a/examples/03-ui-components/13-custom-ui/src/MUIFormattingToolbar.tsx +++ b/examples/03-ui-components/13-custom-ui/src/MUIFormattingToolbar.tsx @@ -303,6 +303,10 @@ function MUITextAlignButton(props: { editor.focus(); }, [editor, props.textAlignment]); + if (!activeTextAlignment) { + return null; + } + return ( (element: HTMLElement) => { return undefined; } - return parseEmbedElement(element as HTMLEmbedElement); + const { backgroundColor } = parseDefaultProps(element); + + return { + ...parseEmbedElement(element as HTMLEmbedElement), + backgroundColor, + }; } if (element.tagName === "FIGURE") { @@ -48,8 +53,11 @@ export const fileParse = () => (element: HTMLElement) => { const { targetElement, caption } = parsedFigure; + const { backgroundColor } = parseDefaultProps(element); + return { ...parseEmbedElement(targetElement as HTMLEmbedElement), + backgroundColor, caption, }; } diff --git a/packages/core/src/blocks/Heading/block.ts b/packages/core/src/blocks/Heading/block.ts index ffe6844693..7181298d1f 100644 --- a/packages/core/src/blocks/Heading/block.ts +++ b/packages/core/src/blocks/Heading/block.ts @@ -1,6 +1,10 @@ import { createBlockConfig, createBlockSpec } from "../../schema/index.js"; import { createBlockNoteExtension } from "../../editor/BlockNoteExtension.js"; -import { defaultProps } from "../defaultProps.js"; +import { + addDefaultPropsExternalHTML, + defaultProps, + parseDefaultProps, +} from "../defaultProps.js"; import { createToggleWrapper } from "../ToggleWrapper/createToggleWrapper.js"; const HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const; @@ -65,6 +69,7 @@ export const createHeadingBlockSpec = createBlockSpec( } return { + ...parseDefaultProps(e), level, }; }, @@ -83,6 +88,7 @@ export const createHeadingBlockSpec = createBlockSpec( }, toExternalHTML(block) { const dom = document.createElement(`h${block.props.level}`); + addDefaultPropsExternalHTML(block.props, dom); return { dom, diff --git a/packages/core/src/blocks/Image/block.ts b/packages/core/src/blocks/Image/block.ts index 3f76bb260c..83138c8842 100644 --- a/packages/core/src/blocks/Image/block.ts +++ b/packages/core/src/blocks/Image/block.ts @@ -4,7 +4,7 @@ import { createBlockConfig, createBlockSpec, } from "../../schema/index.js"; -import { defaultProps } from "../defaultProps.js"; +import { defaultProps, parseDefaultProps } from "../defaultProps.js"; import { parseFigureElement } from "../File/helpers/parse/parseFigureElement.js"; import { createResizableFileBlockWrapper } from "../File/helpers/render/createResizableFileBlockWrapper.js"; import { createFigureWithCaption } from "../File/helpers/toExternalHTML/createFigureWithCaption.js"; @@ -62,7 +62,12 @@ export const imageParse = return undefined; } - return parseImageElement(element as HTMLImageElement); + const { backgroundColor } = parseDefaultProps(element); + + return { + ...parseImageElement(element as HTMLImageElement), + backgroundColor, + }; } if (element.tagName === "FIGURE") { @@ -73,8 +78,11 @@ export const imageParse = const { targetElement, caption } = parsedFigure; + const { backgroundColor } = parseDefaultProps(element); + return { ...parseImageElement(targetElement as HTMLImageElement), + backgroundColor, caption, }; } diff --git a/packages/core/src/blocks/ListItem/BulletListItem/block.ts b/packages/core/src/blocks/ListItem/BulletListItem/block.ts index 538183ba72..698bc8a828 100644 --- a/packages/core/src/blocks/ListItem/BulletListItem/block.ts +++ b/packages/core/src/blocks/ListItem/BulletListItem/block.ts @@ -1,6 +1,10 @@ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js"; import { createBlockConfig, createBlockSpec } from "../../../schema/index.js"; -import { defaultProps } from "../../defaultProps.js"; +import { + addDefaultPropsExternalHTML, + defaultProps, + parseDefaultProps, +} from "../../defaultProps.js"; import { handleEnter } from "../../utils/listItemEnterHandler.js"; import { getListItemContent } from "../getListItemContent.js"; @@ -27,23 +31,23 @@ export const createBulletListItemBlockSpec = createBlockSpec( }, parse(element) { if (element.tagName !== "LI") { - return false; + return undefined; } const parent = element.parentElement; if (parent === null) { - return false; + return undefined; } if ( parent.tagName === "UL" || (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL") ) { - return {}; + return parseDefaultProps(element); } - return false; + return undefined; }, // As `li` elements can contain multiple paragraphs, we need to merge their contents // into a single one so that ProseMirror can parse everything correctly. @@ -60,6 +64,17 @@ export const createBulletListItemBlockSpec = createBlockSpec( contentDOM: dom, }; }, + toExternalHTML(block) { + const li = document.createElement("li"); + const p = document.createElement("p"); + addDefaultPropsExternalHTML(block.props, li); + li.appendChild(p); + + return { + dom: li, + contentDOM: p, + }; + }, }, [ createBlockNoteExtension({ diff --git a/packages/core/src/blocks/ListItem/CheckListItem/block.ts b/packages/core/src/blocks/ListItem/CheckListItem/block.ts index 98574abd6f..af04233736 100644 --- a/packages/core/src/blocks/ListItem/CheckListItem/block.ts +++ b/packages/core/src/blocks/ListItem/CheckListItem/block.ts @@ -1,6 +1,10 @@ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js"; import { createBlockConfig, createBlockSpec } from "../../../schema/index.js"; -import { defaultProps } from "../../defaultProps.js"; +import { + addDefaultPropsExternalHTML, + defaultProps, + parseDefaultProps, +} from "../../defaultProps.js"; import { handleEnter } from "../../utils/listItemEnterHandler.js"; import { getListItemContent } from "../getListItemContent.js"; @@ -30,22 +34,22 @@ export const createCheckListItemBlockSpec = createBlockSpec( if (element.tagName === "input") { // Ignore if we already parsed an ancestor list item to avoid double-parsing. if (element.closest("[data-content-type]") || element.closest("li")) { - return; + return undefined; } if ((element as HTMLInputElement).type === "checkbox") { return { checked: (element as HTMLInputElement).checked }; } - return; + return undefined; } if (element.tagName !== "LI") { - return; + return undefined; } const parent = element.parentElement; if (parent === null) { - return; + return undefined; } if ( @@ -57,10 +61,10 @@ export const createCheckListItemBlockSpec = createBlockSpec( null; if (checkbox === null) { - return; + return undefined; } - return { checked: checkbox.checked }; + return { ...parseDefaultProps(element), checked: checkbox.checked }; } return; @@ -69,7 +73,7 @@ export const createCheckListItemBlockSpec = createBlockSpec( // into a single one so that ProseMirror can parse everything correctly. parseContent: ({ el, schema }) => getListItemContent(el, schema, "checkListItem"), - render(block) { + render(block, editor) { const dom = document.createDocumentFragment(); const checkbox = document.createElement("input"); checkbox.type = "checkbox"; @@ -77,6 +81,9 @@ export const createCheckListItemBlockSpec = createBlockSpec( if (block.props.checked) { checkbox.setAttribute("checked", ""); } + checkbox.addEventListener("change", () => { + editor.updateBlock(block, { props: { checked: !block.props.checked } }); + }); // We use a

tag, because for

  • tags we'd need a