diff --git a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts
index dd0350483..a39c2d7b9 100644
--- a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts
+++ b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts
@@ -144,6 +144,19 @@ function serializeBlock<
// We wrap the output in an `li` element for list items, and so we want to
// add the attributes to that element instead as it is the "root".
if (!listType) {
+ // Copies the styles and prop-related attributes from the `blockContent`
+ // element onto its first child, as the `blockContent` element is omitted
+ // from external HTML. This is so prop data is preserved via `data-*`
+ // attributes or inline styles.
+ //
+ // The styles are specifically for default props on default blocks, as
+ // they get converted from `data-*` attributes for external HTML. Will
+ // need to revisit this when we convert default blocks to use the custom
+ // block API.
+ const style = ret.dom.getAttribute("style");
+ if (style) {
+ (ret.dom.firstChild! as HTMLElement).setAttribute("style", style);
+ }
for (const attr of blockContentDataAttributes) {
(ret.dom.firstChild! as HTMLElement).setAttribute(
attr.name,
@@ -179,9 +192,24 @@ function serializeBlock<
fragment.append(list);
}
const li = doc.createElement("li");
+
+ // Copies the styles and prop-related attributes from the `blockContent`
+ // element onto its first child, as the `blockContent` element is omitted
+ // from external HTML. This is so prop data is preserved via `data-*`
+ // attributes or inline styles.
+ //
+ // The styles are specifically for default props on default blocks, as
+ // they get converted from `data-*` attributes for external HTML. Will
+ // need to revisit this when we convert default blocks to use the custom
+ // block API.
+ const style = ret.dom.getAttribute("style");
+ if (style) {
+ li.setAttribute("style", style);
+ }
for (const attr of blockContentDataAttributes) {
li.setAttribute(attr.name, attr.value);
}
+
li.append(elementFragment);
fragment.lastChild!.appendChild(li);
} else {
diff --git a/packages/core/src/blocks/defaultBlockHelpers.ts b/packages/core/src/blocks/defaultBlockHelpers.ts
index fbba956c8..b8220e310 100644
--- a/packages/core/src/blocks/defaultBlockHelpers.ts
+++ b/packages/core/src/blocks/defaultBlockHelpers.ts
@@ -1,5 +1,6 @@
import { blockToNode } from "../api/nodeConversions/blockToNode.js";
import type { BlockNoteEditor } from "../editor/BlockNoteEditor.js";
+import { COLORS_DEFAULT } from "../editor/defaultColors.js";
import type {
BlockNoDefaults,
BlockSchema,
@@ -55,14 +56,17 @@ export function createDefaultBlockDOMOutputSpec(
// Function used to convert default blocks to HTML. It uses the corresponding
// node's `renderHTML` method to do the conversion by using a default
-// `DOMSerializer`.
+// `DOMSerializer`. The `external` flag is used to modify the resulting HTML for
+// external use. This just involves changing props being rendered from `data-*`
+// attributes to inline styles.
export const defaultBlockToHTML = <
BSchema extends BlockSchema,
I extends InlineContentSchema,
S extends StyleSchema
>(
block: BlockNoDefaults Paragraph list item Caption Caption Paragraph list item Caption Paragraph list item Caption Paragraph 1 Paragraph 1 Numbered List Item 1 Bullet List Item 1Heading
2Heading
2Heading
2Heading 1
+Heading 1
-
+
Heading
@@ -6,7 +6,9 @@
Paragraph
Paragraph
Plain Red Text diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorProp.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorProp.json index f2ebc5ed9..15f5d0729 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorProp.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorProp.json @@ -4,30 +4,13 @@ "content": [ { "styles": {}, - "text": "Red Background", + "text": "Blue Background", "type": "text", }, ], "id": "1", "props": { - "backgroundColor": "red", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Green Background", - "type": "text", - }, - ], - "id": "2", - "props": { - "backgroundColor": "green", + "backgroundColor": "blue", "textAlignment": "left", "textColor": "default", }, @@ -42,7 +25,7 @@ "type": "text", }, ], - "id": "3", + "id": "2", "props": { "backgroundColor": "blue", "textAlignment": "left", diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json index 0f1dfc15e..8afe915ba 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json @@ -4,21 +4,9 @@ "content": [ { "styles": { - "backgroundColor": "red", - }, - "text": "Red Background", - "type": "text", - }, - { - "styles": {}, - "text": " ", - "type": "text", - }, - { - "styles": { - "backgroundColor": "green", + "backgroundColor": "blue", }, - "text": "Green Background", + "text": "Blue Background", "type": "text", }, { diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorProp.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorProp.json index 7480fcab3..4211362bf 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorProp.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorProp.json @@ -4,7 +4,7 @@ "content": [ { "styles": {}, - "text": "Red Paragraph", + "text": "Blue Text", "type": "text", }, ], @@ -12,7 +12,7 @@ "props": { "backgroundColor": "default", "textAlignment": "left", - "textColor": "red", + "textColor": "blue", }, "type": "paragraph", }, @@ -21,28 +21,11 @@ "content": [ { "styles": {}, - "text": "Green Paragraph", + "text": "Blue Text", "type": "text", }, ], "id": "2", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "green", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Blue Paragraph", - "type": "text", - }, - ], - "id": "3", "props": { "backgroundColor": "default", "textAlignment": "left", diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json index faeeee527..e78e1a4b3 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json @@ -4,21 +4,9 @@ "content": [ { "styles": { - "textColor": "red", - }, - "text": "Red Text", - "type": "text", - }, - { - "styles": {}, - "text": " ", - "type": "text", - }, - { - "styles": { - "textColor": "green", + "textColor": "blue", }, - "text": "Green Text", + "text": "Blue Text", "type": "text", }, { diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/twoTables.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/twoTables.json index 3ffbb3ead..1def7a8e3 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/twoTables.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/twoTables.json @@ -45,7 +45,7 @@ { "styles": {}, "text": " - + Name: [Company Representative] Title: Chief Executive Officer", "type": "text", diff --git a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts index 375bfd098..2ec30e07d 100644 --- a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts +++ b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts @@ -20,11 +20,11 @@ export const parseTestInstancesHTML: TestInstance< testCase: { name: "basicBlockTypes", content: `
Paragraph
-None Bold Italic Underline Strikethrough All
Paragraph
+None Bold Italic Underline Strikethrough All
Bullet List Item
-Bullet List Item
-Nested Bullet List Item
-Nested Bullet List Item
-Bullet List Item
-Numbered List Item
-Numbered List Item
-Nested Numbered List Item
-Nested Numbered List Item
-Numbered List Item
-Checked List Item
-Checked List Item
-Nested Checked List Item
-Nested Checked List Item
-Checked List Item
-Bullet List Item
+Bullet List Item
+Nested Bullet List Item
+Nested Bullet List Item
+Bullet List Item
+Numbered List Item
+Numbered List Item
+Nested Numbered List Item
+Nested Numbered List Item
+Numbered List Item
+Checked List Item
+Checked List Item
+Nested Checked List Item
+Nested Checked List Item
+Checked List Item
+
-
-
Image Caption
-Image Caption
+ `, }, executeTest: testParseHTML, }, @@ -276,27 +276,27 @@ export const parseTestInstancesHTML: TestInstance< testCase: { name: "deepNestedContent", content: `Paragraph
-Bold Italic Underline Strikethrough All
Paragraph
+Bold Italic Underline Strikethrough All
Nested Paragraph
-Nested Paragraph
+ `, }, executeTest: testParseHTML, }, @@ -315,21 +315,21 @@ export const parseTestInstancesHTML: TestInstance< testCase: { name: "twoTables", content: `
- Company - |
-
- Example Company Inc. -- Name: [Company Representative] - -Title: Chief Executive Officer - |
-
Company
+Example Company Inc.
++
Name: [Company Representative]
+ +Title: Chief Executive Officer
+