From 8cad7bdf622e9b6c25503c31996de3d141b8c501 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Sat, 12 Apr 2025 01:12:43 +0200 Subject: [PATCH 01/14] Fixed parsing of numbered list start index, background color mark, and text color mark --- .../NumberedListItemBlockContent.ts | 2 +- packages/core/src/blocks/defaultProps.ts | 53 +++++ .../BackgroundColorExtension.ts | 21 +- .../BackgroundColor/BackgroundColorMark.ts | 18 +- .../TextColor/TextColorExtension.ts | 18 +- .../src/extensions/TextColor/TextColorMark.ts | 14 +- .../ServerBlockNoteEditor.test.ts.snap | 55 ++--- .../multi-column/undefined/external.html | 2 +- .../html/backgroundColorStyle.json | 45 +++++ .../parse/__snapshots__/html/boldStyle.json | 45 +++++ .../parse/__snapshots__/html/imageWidth.json | 17 ++ .../parse/__snapshots__/html/italicStyle.json | 45 +++++ .../__snapshots__/html/orderedListStart.json | 54 +++++ .../parse/__snapshots__/html/strikeStyle.json | 57 ++++++ .../__snapshots__/html/textColorStyle.json | 45 +++++ .../__snapshots__/html/underlineStyle.json | 33 +++ .../parse/parseTestInstances.ts | 189 +++--------------- 17 files changed, 460 insertions(+), 253 deletions(-) create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/boldStyle.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/imageWidth.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/italicStyle.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/orderedListStart.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/strikeStyle.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/underlineStyle.json diff --git a/packages/core/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts b/packages/core/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts index 6c0f72a0a0..37e04beb27 100644 --- a/packages/core/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +++ b/packages/core/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts @@ -126,7 +126,7 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({ const startIndex = parseInt(parent.getAttribute("start") || "1") || 1; - if (element.previousSibling || startIndex === 1) { + if (element.previousElementSibling || startIndex === 1) { return {}; } diff --git a/packages/core/src/blocks/defaultProps.ts b/packages/core/src/blocks/defaultProps.ts index 4fb0b838c8..3a596b880b 100644 --- a/packages/core/src/blocks/defaultProps.ts +++ b/packages/core/src/blocks/defaultProps.ts @@ -1,3 +1,5 @@ +import { Attribute } from "@tiptap/core"; + import type { Props, PropSchema } from "../schema/index.js"; // TODO: this system should probably be moved / refactored. @@ -22,3 +24,54 @@ export type DefaultProps = Props; // `blockContent` nodes. Ensures that they are not redundantly added to // a custom block's TipTap node attributes. export const inheritedProps = ["backgroundColor", "textColor"]; + +export const getBackgroundColorAttribute = ( + attributeName = "backgroundColor" +): Attribute => ({ + default: defaultProps.backgroundColor.default, + parseHTML: (element) => { + if (element.hasAttribute("data-background-color")) { + return element.getAttribute("data-background-color"); + } + + if (element.style.backgroundColor) { + return element.style.backgroundColor; + } + + return defaultProps.backgroundColor.default; + }, + renderHTML: (attributes) => { + if (attributes[attributeName] === defaultProps.backgroundColor.default) { + return {}; + } + + return { + "data-background-color": attributes[attributeName], + }; + }, +}); + +export const getTextColorAttribute = ( + attributeName = "textColor" +): Attribute => ({ + default: defaultProps.textColor.default, + parseHTML: (element) => { + if (element.hasAttribute("data-text-color")) { + return element.getAttribute("data-text-color"); + } + + if (element.style.color) { + return element.style.color; + } + + return defaultProps.textColor.default; + }, + renderHTML: (attributes) => { + if (attributes[attributeName] === defaultProps.textColor.default) { + return {}; + } + return { + "data-text-color": attributes[attributeName], + }; + }, +}); diff --git a/packages/core/src/extensions/BackgroundColor/BackgroundColorExtension.ts b/packages/core/src/extensions/BackgroundColor/BackgroundColorExtension.ts index fca4922a1a..61a8b8c14b 100644 --- a/packages/core/src/extensions/BackgroundColor/BackgroundColorExtension.ts +++ b/packages/core/src/extensions/BackgroundColor/BackgroundColorExtension.ts @@ -1,5 +1,5 @@ import { Extension } from "@tiptap/core"; -import { defaultProps } from "../../blocks/defaultProps.js"; +import { getBackgroundColorAttribute } from "../../blocks/defaultProps.js"; export const BackgroundColorExtension = Extension.create({ name: "blockBackgroundColor", @@ -9,24 +9,7 @@ export const BackgroundColorExtension = Extension.create({ { types: ["blockContainer", "tableCell", "tableHeader"], attributes: { - backgroundColor: { - default: defaultProps.backgroundColor.default, - parseHTML: (element) => - element.hasAttribute("data-background-color") - ? element.getAttribute("data-background-color") - : defaultProps.backgroundColor.default, - renderHTML: (attributes) => { - if ( - attributes.backgroundColor === - defaultProps.backgroundColor.default - ) { - return {}; - } - return { - "data-background-color": attributes.backgroundColor, - }; - }, - }, + backgroundColor: getBackgroundColorAttribute(), }, }, ]; diff --git a/packages/core/src/extensions/BackgroundColor/BackgroundColorMark.ts b/packages/core/src/extensions/BackgroundColor/BackgroundColorMark.ts index 03c57dd4ac..1ef31cb1f4 100644 --- a/packages/core/src/extensions/BackgroundColor/BackgroundColorMark.ts +++ b/packages/core/src/extensions/BackgroundColor/BackgroundColorMark.ts @@ -1,4 +1,5 @@ import { Mark } from "@tiptap/core"; +import { getBackgroundColorAttribute } from "../../blocks/defaultProps.js"; import { createStyleSpecFromTipTapMark } from "../../schema/index.js"; const BackgroundColorMark = Mark.create({ @@ -6,13 +7,7 @@ const BackgroundColorMark = Mark.create({ addAttributes() { return { - stringValue: { - default: undefined, - parseHTML: (element) => element.getAttribute("data-background-color"), - renderHTML: (attributes) => ({ - "data-background-color": attributes.stringValue, - }), - }, + stringValue: getBackgroundColorAttribute("stringValue"), }; }, @@ -25,10 +20,11 @@ const BackgroundColorMark = Mark.create({ return false; } - if (element.hasAttribute("data-background-color")) { - return { - stringValue: element.getAttribute("data-background-color"), - }; + if ( + element.hasAttribute("data-background-color") || + element.style.backgroundColor + ) { + return {}; } return false; diff --git a/packages/core/src/extensions/TextColor/TextColorExtension.ts b/packages/core/src/extensions/TextColor/TextColorExtension.ts index 4060fea6d6..eddb96f9e7 100644 --- a/packages/core/src/extensions/TextColor/TextColorExtension.ts +++ b/packages/core/src/extensions/TextColor/TextColorExtension.ts @@ -1,5 +1,5 @@ import { Extension } from "@tiptap/core"; -import { defaultProps } from "../../blocks/defaultProps.js"; +import { getTextColorAttribute } from "../../blocks/defaultProps.js"; export const TextColorExtension = Extension.create({ name: "blockTextColor", @@ -9,21 +9,7 @@ export const TextColorExtension = Extension.create({ { types: ["blockContainer", "tableCell", "tableHeader"], attributes: { - textColor: { - default: defaultProps.textColor.default, - parseHTML: (element) => - element.hasAttribute("data-text-color") - ? element.getAttribute("data-text-color") - : defaultProps.textColor.default, - renderHTML: (attributes) => { - if (attributes.textColor === defaultProps.textColor.default) { - return {}; - } - return { - "data-text-color": attributes.textColor, - }; - }, - }, + textColor: getTextColorAttribute(), }, }, ]; diff --git a/packages/core/src/extensions/TextColor/TextColorMark.ts b/packages/core/src/extensions/TextColor/TextColorMark.ts index 2f5c314ba3..cc42f9a749 100644 --- a/packages/core/src/extensions/TextColor/TextColorMark.ts +++ b/packages/core/src/extensions/TextColor/TextColorMark.ts @@ -1,18 +1,14 @@ import { Mark } from "@tiptap/core"; +import { getTextColorAttribute } from "../../blocks/defaultProps.js"; import { createStyleSpecFromTipTapMark } from "../../schema/index.js"; const TextColorMark = Mark.create({ name: "textColor", + priority: 1000, addAttributes() { return { - stringValue: { - default: undefined, - parseHTML: (element) => element.getAttribute("data-text-color"), - renderHTML: (attributes) => ({ - "data-text-color": attributes.stringValue, - }), - }, + stringValue: getTextColorAttribute("stringValue"), }; }, @@ -25,8 +21,8 @@ const TextColorMark = Mark.create({ return false; } - if (element.hasAttribute("data-text-color")) { - return { stringValue: element.getAttribute("data-text-color") }; + if (element.hasAttribute("data-text-color") || element.style.color) { + return {}; } return false; diff --git a/packages/server-util/src/context/__snapshots__/ServerBlockNoteEditor.test.ts.snap b/packages/server-util/src/context/__snapshots__/ServerBlockNoteEditor.test.ts.snap index 5bd969bfa8..ac3cc4b2c5 100644 --- a/packages/server-util/src/context/__snapshots__/ServerBlockNoteEditor.test.ts.snap +++ b/packages/server-util/src/context/__snapshots__/ServerBlockNoteEditor.test.ts.snap @@ -2,7 +2,7 @@ exports[`Test ServerBlockNoteEditor > converts to HTML (blocksToFullHTML) 1`] = `"

Heading 2

Paragraph

list item

Example

Caption

Example

Caption

"`; -exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLossy) 1`] = `"

Heading 2

Paragraph

Example
Caption
Example

Caption

"`; +exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLossy) 1`] = `"

Heading 2

Paragraph

Example
Caption
Example

Caption

"`; exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLossy) 2`] = ` [ @@ -26,12 +26,12 @@ exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLos "type": "text", }, ], - "id": "0", + "id": "1", "props": { - "backgroundColor": "default", + "backgroundColor": "blue", "level": 2, "textAlignment": "right", - "textColor": "default", + "textColor": "yellow", }, "type": "heading", }, @@ -44,9 +44,9 @@ exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLos "type": "text", }, ], - "id": "1", + "id": "2", "props": { - "backgroundColor": "default", + "backgroundColor": "red", "textAlignment": "left", "textColor": "default", }, @@ -61,7 +61,7 @@ exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLos "type": "text", }, ], - "id": "2", + "id": "3", "props": { "backgroundColor": "default", "textAlignment": "left", @@ -72,7 +72,7 @@ exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLos { "children": [], "content": undefined, - "id": "3", + "id": "4", "props": { "backgroundColor": "default", "caption": "Caption", @@ -86,43 +86,18 @@ exports[`Test ServerBlockNoteEditor > converts to and from HTML (blocksToHTMLLos }, { "children": [], - "content": [ - { - "content": [ - { - "styles": {}, - "text": "Example", - "type": "text", - }, - ], - "href": "exampleURL", - "type": "link", - }, - ], - "id": "4", - "props": { - "backgroundColor": "default", - "textAlignment": "left", - "textColor": "default", - }, - "type": "paragraph", - }, - { - "children": [], - "content": [ - { - "styles": {}, - "text": "Caption", - "type": "text", - }, - ], + "content": undefined, "id": "5", "props": { "backgroundColor": "default", + "caption": "Caption", + "name": "Example", + "previewWidth": 256, + "showPreview": false, "textAlignment": "left", - "textColor": "default", + "url": "exampleURL", }, - "type": "paragraph", + "type": "image", }, ] `; diff --git a/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html b/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html index cbbcb6592b..b0d9e1665e 100644 --- a/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html +++ b/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html @@ -1 +1 @@ -

Column Paragraph 0

Column Paragraph 1

Column Paragraph 2

Column Paragraph 3

\ No newline at end of file +

Column Paragraph 0

Column Paragraph 1

Column Paragraph 2

Column Paragraph 3

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json new file mode 100644 index 0000000000..0f1dfc15e7 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/backgroundColorStyle.json @@ -0,0 +1,45 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "backgroundColor": "red", + }, + "text": "Red Background", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "backgroundColor": "green", + }, + "text": "Green Background", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "backgroundColor": "blue", + }, + "text": "Blue Background", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/boldStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/boldStyle.json new file mode 100644 index 0000000000..6a084ab50f --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/boldStyle.json @@ -0,0 +1,45 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "bold": true, + }, + "text": "Bold", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "bold": true, + }, + "text": "Bold", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "bold": true, + }, + "text": "Bold", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/imageWidth.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/imageWidth.json new file mode 100644 index 0000000000..61fe6080a0 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/imageWidth.json @@ -0,0 +1,17 @@ +[ + { + "children": [], + "content": undefined, + "id": "1", + "props": { + "backgroundColor": "default", + "caption": "", + "name": "", + "previewWidth": 100, + "showPreview": true, + "textAlignment": "left", + "url": "exampleURL", + }, + "type": "image", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/italicStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/italicStyle.json new file mode 100644 index 0000000000..27d939a344 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/italicStyle.json @@ -0,0 +1,45 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "italic": true, + }, + "text": "Italic", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "italic": true, + }, + "text": "Italic", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "italic": true, + }, + "text": "Italic", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/orderedListStart.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/orderedListStart.json new file mode 100644 index 0000000000..3532f949a8 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/orderedListStart.json @@ -0,0 +1,54 @@ +[ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "List Item 2", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "start": 2, + "textAlignment": "left", + "textColor": "default", + }, + "type": "numberedListItem", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "List Item 3", + "type": "text", + }, + ], + "id": "2", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "numberedListItem", + }, + { + "children": [], + "content": [ + { + "styles": {}, + "text": "List Item 4", + "type": "text", + }, + ], + "id": "3", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "numberedListItem", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/strikeStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/strikeStyle.json new file mode 100644 index 0000000000..cedb32736f --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/strikeStyle.json @@ -0,0 +1,57 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "strike": true, + }, + "text": "Strike", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "strike": true, + }, + "text": "Strike", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "strike": true, + }, + "text": "Strike", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "strike": true, + }, + "text": "Strike", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json new file mode 100644 index 0000000000..faeeee5277 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/textColorStyle.json @@ -0,0 +1,45 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "textColor": "red", + }, + "text": "Red Text", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "green", + }, + "text": "Green Text", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "blue", + }, + "text": "Blue Text", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/underlineStyle.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/underlineStyle.json new file mode 100644 index 0000000000..22472ff797 --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/underlineStyle.json @@ -0,0 +1,33 @@ +[ + { + "children": [], + "content": [ + { + "styles": { + "underline": true, + }, + "text": "Underline", + "type": "text", + }, + { + "styles": {}, + "text": " ", + "type": "text", + }, + { + "styles": { + "underline": true, + }, + "text": "Underline", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts index 1953d1ca75..99f11cd837 100644 --- a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts +++ b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts @@ -348,170 +348,47 @@ export const parseTestInstancesHTML: TestInstance< }, { testCase: { - name: "notion", - content: `

Heading 1

-

Heading 2

-

Heading 3

-

Paragraph 1

-

Nested Paragraph 1

-

Nested Paragraph 2

-

Paragraph -With Hard Break

-

Bold Italic Underline Strikethrough All

- -
    -
  1. Numbered List Item 1
  2. -
  3. Numbered List Item 2
  4. -
-

Background Color Paragraph

-

!https://www.pulsecarshalton.co.uk/wp-content/uploads/2016/08/jk-placeholder-image.jpg

- - - - - - - - - - - - - - - - - - - - -
Cell 1Cell 2Cell 3
Cell 4Cell 5Cell 6
Cell 7Cell 8Cell 9
-

Paragraph

-`, - }, - executeTest: testParseHTML, - }, - { - testCase: { - name: "googleDocs", - content: ` - - -

Heading 1

-

Heading 2

-

Heading 3

-

Paragraph 1

-

Paragraph 2

-

Paragraph 3

-

Paragraph With
Hard Break

-

Bold Italic Underline Strikethrough All

-
    -
  • -

    Bullet List Item 1

    -
  • -
      -
    • -

      Nested Bullet List Item 1

      -
    • -
        -
      1. -

        Nested Numbered List Item 1

        -
      2. -
      3. -

        Nested Numbered List Item 2

        -
      4. -
      -
    • -

      Nested Bullet List Item 2

      -
    • -
    -
  • -

    Bullet List Item 2

    -
  • -
-
    -
  1. -

    Numbered List Item 1

    -
  2. -
  3. -

    Numbered List Item 2

    -
  4. -
-

-
-
- ----- - - - - - - - - - - - - - - - - - -
-

Cell 1

-
-

Cell 2

-
-

Cell 3

-
-

Cell 4

-
-

Cell 5

-
-

Cell 6

-
-

Cell 7

-
-

Cell 8

-
-

Cell 9

-
-
-

Paragraph

-
-
`, + name: "orderedListStart", + content: `
    +
  1. List Item 2
  2. +
  3. List Item 3
  4. +
  5. List Item 4
  6. +
`, }, executeTest: testParseHTML, }, { testCase: { - name: "codeBlocks", - content: `
console.log("Should default to JS")
-
console.log("Should parse TS from data-language")
-
print("Should parse Python from language- class")
-
console.log("Should prioritize TS from data-language over language- class")
`, + name: "imageWidth", + content: ``, }, executeTest: testParseHTML, }, + // { + // testCase: { + // name: "textAlignmentProp", + // content: `

Text Align Center

`, + // }, + // executeTest: testParseHTML, + // }, + // { + // testCase: { + // name: "textColorProp", + // content: `

Red Paragraph

+ //

Green Paragraph

+ //

Blue Paragraph

`, + // }, + // executeTest: testParseHTML, + // }, + // { + // testCase: { + // name: "backgroundColorProp", + // content: `

Red Background

+ //

Green Background

+ //

Blue Background

`, + // }, + // executeTest: testParseHTML, + // }, ]; export const parseTestInstancesMarkdown: TestInstance< From 1b23c70cc8bd136978de41c294c9439744017b27 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Thu, 17 Apr 2025 10:25:42 +0200 Subject: [PATCH 02/14] Fixes --- .../exportParseEqualityTestInstances.ts | 178 +++++++++++++++ .../parse/__snapshots__/html/googleDocs.json | 147 +++++++++--- .../parse/parseTestInstances.ts | 209 ++++++++++++++++++ 3 files changed, 509 insertions(+), 25 deletions(-) diff --git a/tests/src/unit/core/formatConversion/exportParseEquality/exportParseEqualityTestInstances.ts b/tests/src/unit/core/formatConversion/exportParseEquality/exportParseEqualityTestInstances.ts index 63d3552df0..f8c886568b 100644 --- a/tests/src/unit/core/formatConversion/exportParseEquality/exportParseEqualityTestInstances.ts +++ b/tests/src/unit/core/formatConversion/exportParseEquality/exportParseEqualityTestInstances.ts @@ -21,3 +21,181 @@ export const exportParseEqualityTestInstancesBlockNoteHTML: TestInstance< testCase, executeTest: testExportParseEqualityBlockNoteHTML, })); + +export const exportParseEqualityTestInstancesHTML: TestInstance< + ExportParseEqualityTestCase< + TestBlockSchema, + TestInlineContentSchema, + TestStyleSchema + >, + TestBlockSchema, + TestInlineContentSchema, + TestStyleSchema +>[] = [ + { + testCase: { + name: "schema/blocks", + content: [ + { + type: "paragraph", + content: "Paragraph", + }, + { + type: "heading", + content: "Heading", + }, + { + type: "quote", + content: "Quote", + }, + { + type: "bulletListItem", + content: "Bullet List Item", + }, + { + type: "numberedListItem", + content: "Numbered List Item", + }, + { + type: "checkListItem", + content: "Check List Item", + }, + { + type: "codeBlock", + content: "Code", + }, + { + type: "table", + content: { + type: "tableContent", + rows: [ + { + cells: ["Table Cell", "Table Cell"], + }, + { + cells: ["Table Cell", "Table Cell"], + }, + ], + }, + }, + ], + }, + executeTest: testExportParseEqualityHTML, + }, + { + testCase: { + name: "schema/blockProps", + content: [ + { + type: "paragraph", + content: "Paragraph", + props: { + textColor: "red", + backgroundColor: "blue", + textAlignment: "center", + }, + }, + { + type: "heading", + content: "Heading", + props: { + level: 2, + }, + }, + { + type: "checkListItem", + content: "Check List Item", + props: { + checked: true, + textColor: "red", + backgroundColor: "blue", + textAlignment: "center", + }, + }, + { + type: "codeBlock", + content: "Code", + props: { language: "javascript" }, + }, + ], + }, + executeTest: testExportParseEqualityHTML, + }, + { + testCase: { + name: "schema/inlineContent", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "Text ", + styles: {}, + }, + { + type: "link", + content: "Link", + href: "https://example.com", + }, + ], + }, + ], + }, + executeTest: testExportParseEqualityHTML, + }, + { + testCase: { + name: "schema/styles", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "T", + styles: { + bold: true, + italic: true, + underline: true, + strike: true, + // Code cannot be applied on top of other styles. + // code: true, + textColor: "red", + backgroundColor: "blue", + }, + }, + ], + }, + ], + }, + executeTest: testExportParseEqualityHTML, + }, + // TODO: Tests failing + // { + // testCase: { + // name: "lists/nested", + // content: [ + // { + // type: "bulletListItem", + // content: "List Item 1", + // children: [ + // { + // type: "bulletListItem", + // content: "Nested List Item 1", + // }, + // { + // type: "bulletListItem", + // content: "Nested List Item 2", + // }, + // ], + // }, + // { + // type: "bulletListItem", + // content: "List Item 2", + // }, + // ], + // }, + // executeTest: testExportParseEqualityHTML, + // }, +]; diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/googleDocs.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/googleDocs.json index 5a7912dcd1..aeee039f19 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/googleDocs.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/googleDocs.json @@ -5,6 +5,7 @@ { "styles": { "bold": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Heading 1", "type": "text", @@ -25,6 +26,7 @@ { "styles": { "bold": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Heading 2", "type": "text", @@ -45,6 +47,7 @@ { "styles": { "bold": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Heading 3", "type": "text", @@ -63,7 +66,9 @@ "children": [], "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Paragraph 1", "type": "text", }, @@ -80,7 +85,9 @@ "children": [], "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Paragraph 2", "type": "text", }, @@ -97,7 +104,9 @@ "children": [], "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Paragraph 3", "type": "text", }, @@ -114,7 +123,9 @@ "children": [], "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Paragraph With Hard Break", "type": "text", @@ -134,36 +145,45 @@ Hard Break", { "styles": { "bold": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Bold", "type": "text", }, { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": " ", "type": "text", }, { "styles": { "italic": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Italic", "type": "text", }, { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": " Underline ", "type": "text", }, { "styles": { "strike": true, + "textColor": "rgb(0, 0, 0)", }, "text": "Strikethrough", "type": "text", }, { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": " ", "type": "text", }, @@ -172,6 +192,7 @@ Hard Break", "bold": true, "italic": true, "strike": true, + "textColor": "rgb(255, 0, 0)", }, "text": "All", "type": "text", @@ -194,7 +215,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Nested Numbered List Item 1", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Nested Numbered List Item 1", "type": "text", }, ], @@ -211,7 +239,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Nested Numbered List Item 2", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Nested Numbered List Item 2", "type": "text", }, ], @@ -227,7 +262,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Nested Bullet List Item 1", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Nested Bullet List Item 1", "type": "text", }, ], @@ -244,7 +286,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Nested Bullet List Item 2", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Nested Bullet List Item 2", "type": "text", }, ], @@ -260,7 +309,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Bullet List Item 1", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Bullet List Item 1", "type": "text", }, ], @@ -277,7 +333,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Bullet List Item 2", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Bullet List Item 2", "type": "text", }, ], @@ -294,7 +357,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Numbered List Item 1", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Numbered List Item 1", "type": "text", }, ], @@ -311,7 +381,14 @@ Hard Break", "content": [ { "styles": {}, - "text": " Numbered List Item 2", + "text": " ", + "type": "text", + }, + { + "styles": { + "textColor": "rgb(0, 0, 0)", + }, + "text": "Numbered List Item 2", "type": "text", }, ], @@ -372,7 +449,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 1", "type": "text", }, @@ -389,7 +468,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 2", "type": "text", }, @@ -406,7 +487,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 3", "type": "text", }, @@ -427,7 +510,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 4", "type": "text", }, @@ -444,7 +529,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 5", "type": "text", }, @@ -461,7 +548,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 6", "type": "text", }, @@ -482,7 +571,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 7", "type": "text", }, @@ -499,7 +590,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 8", "type": "text", }, @@ -516,7 +609,9 @@ Hard Break", { "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Cell 9", "type": "text", }, @@ -545,7 +640,9 @@ Hard Break", "children": [], "content": [ { - "styles": {}, + "styles": { + "textColor": "rgb(0, 0, 0)", + }, "text": "Paragraph", "type": "text", }, diff --git a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts index 99f11cd837..2254316478 100644 --- a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts +++ b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts @@ -346,6 +346,214 @@ export const parseTestInstancesHTML: TestInstance< }, executeTest: testParseHTML, }, + { + testCase: { + name: "notion", + content: `

Heading 1

+

Heading 2

+

Heading 3

+

Paragraph 1

+

Nested Paragraph 1

+

Nested Paragraph 2

+

Paragraph + With Hard Break

+

Bold Italic Underline Strikethrough All

+
    +
  • Bullet List Item 1 +
      +
    • Nested Bullet List Item 1 +
        +
      1. Nested Numbered List Item 1
      2. +
      3. Nested Numbered List Item 2
      4. +
      +
    • +
    • Nested Bullet List Item 2
    • +
    +
  • +
  • Bullet List Item 2
  • +
+
    +
  1. Numbered List Item 1
  2. +
  3. Numbered List Item 2
  4. +
+

Background Color Paragraph

+

!https://www.pulsecarshalton.co.uk/wp-content/uploads/2016/08/jk-placeholder-image.jpg

+ + + + + + + + + + + + + + + + + + + + +
Cell 1Cell 2Cell 3
Cell 4Cell 5Cell 6
Cell 7Cell 8Cell 9
+

Paragraph

+ `, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "googleDocs", + content: ` + + +

Heading 1

+

Heading 2

+

Heading 3

+

Paragraph 1

+

Paragraph 2

+

Paragraph 3

+

Paragraph With
Hard Break

+

Bold Italic Underline Strikethrough All

+
    +
  • +

    Bullet List Item 1

    +
  • +
      +
    • +

      Nested Bullet List Item 1

      +
    • +
        +
      1. +

        Nested Numbered List Item 1

        +
      2. +
      3. +

        Nested Numbered List Item 2

        +
      4. +
      +
    • +

      Nested Bullet List Item 2

      +
    • +
    +
  • +

    Bullet List Item 2

    +
  • +
+
    +
  1. +

    Numbered List Item 1

    +
  2. +
  3. +

    Numbered List Item 2

    +
  4. +
+

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+

Cell 1

+
+

Cell 2

+
+

Cell 3

+
+

Cell 4

+
+

Cell 5

+
+

Cell 6

+
+

Cell 7

+
+

Cell 8

+
+

Cell 9

+
+
+

Paragraph

+
+
`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "codeBlocks", + content: `
console.log("Should default to JS")
+
console.log("Should parse TS from data-language")
+
print("Should parse Python from language- class")
+
console.log("Should prioritize TS from data-language over language- class")
`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "boldStyle", + content: `

Bold Bold Bold

`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "italicStyle", + content: `

Italic Italic Italic

`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "underlineStyle", + content: `

Underline Underline

`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "strikeStyle", + content: `

Strike Strike Strike Strike

`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "textColorStyle", + content: `

Red Text Green Text Blue Text

`, + }, + executeTest: testParseHTML, + }, + { + testCase: { + name: "backgroundColorStyle", + content: `

Red Background Green Background Blue Background

`, + }, + executeTest: testParseHTML, + }, { testCase: { name: "orderedListStart", @@ -364,6 +572,7 @@ export const parseTestInstancesHTML: TestInstance< }, executeTest: testParseHTML, }, + // TODO: Tests failing // { // testCase: { // name: "textAlignmentProp", From 13acc7e8f1e013b7fd1db1f6aac4c3a25926b112 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Wed, 23 Apr 2025 11:32:09 +0200 Subject: [PATCH 03/14] Reverted lost fixes --- .../html/util/serializeBlocksExternalHTML.ts | 49 +++++++------- .../QuoteBlockContent/QuoteBlockContent.ts | 3 +- packages/core/src/pm-nodes/BlockContainer.ts | 17 +++-- .../multi-column/undefined/external.html | 2 +- .../__snapshots__/text/html/basicBlocks.html | 64 +++++++++++++++--- .../text/html/basicBlocksWithProps.html | 67 ++++++++++++++++--- .../text/html/childToParent.html | 14 +++- .../text/html/childrenToNextParent.html | 28 ++++++-- .../html/childrenToNextParentsChildren.html | 49 ++++++++++++-- .../copy/__snapshots__/text/html/image.html | 5 ++ .../text/html/multipleChildren.html | 21 +++++- .../__snapshots__/text/html/nestedImage.html | 19 +++++- .../text/html/partialChildToParent.html | 14 +++- .../html/codeBlock/contains-newlines.html | 7 +- .../html/codeBlock/defaultLanguage.html | 7 +- .../__snapshots__/html/codeBlock/empty.html | 7 +- .../__snapshots__/html/codeBlock/python.html | 7 +- .../__snapshots__/html/complex/misc.html | 19 ++++-- .../export/__snapshots__/html/file/basic.html | 11 ++- .../__snapshots__/html/file/button.html | 8 ++- .../__snapshots__/html/file/nested.html | 22 +++++- .../__snapshots__/html/file/noCaption.html | 11 ++- .../__snapshots__/html/file/noName.html | 10 ++- .../__snapshots__/html/hardbreak/basic.html | 7 +- .../html/hardbreak/between-links.html | 7 +- .../__snapshots__/html/hardbreak/end.html | 7 +- .../__snapshots__/html/hardbreak/link.html | 7 +- .../html/hardbreak/multiple.html | 7 +- .../__snapshots__/html/hardbreak/only.html | 7 +- .../__snapshots__/html/hardbreak/start.html | 7 +- .../__snapshots__/html/hardbreak/styles.html | 7 +- .../__snapshots__/html/image/basic.html | 5 ++ .../__snapshots__/html/image/button.html | 8 ++- .../__snapshots__/html/image/nested.html | 22 +++++- .../__snapshots__/html/image/noCaption.html | 5 ++ .../__snapshots__/html/image/noName.html | 11 ++- .../__snapshots__/html/image/noPreview.html | 5 ++ .../__snapshots__/html/link/adjacent.html | 7 +- .../export/__snapshots__/html/link/basic.html | 7 +- .../__snapshots__/html/link/styled.html | 7 +- .../__snapshots__/html/lists/basic.html | 55 ++++++++++++--- .../__snapshots__/html/lists/nested.html | 55 ++++++++++++--- .../__snapshots__/html/pageBreak/basic.html | 9 ++- .../__snapshots__/html/paragraph/basic.html | 7 +- .../__snapshots__/html/paragraph/empty.html | 7 +- .../html/paragraph/lineBreaks.html | 7 +- .../__snapshots__/html/paragraph/nested.html | 21 +++++- .../__snapshots__/html/paragraph/styled.html | 4 ++ .../html/table/allColWidths.html | 7 +- .../__snapshots__/html/table/basic.html | 7 +- .../__snapshots__/html/table/headerCols.html | 7 +- .../__snapshots__/html/table/headerRows.html | 7 +- .../html/table/mixedCellColors.html | 7 +- .../html/table/mixedColWidths.html | 7 +- .../html/table/mixedRowspansAndColspans.html | 7 +- .../exportParseEqualityTestInstances.ts | 5 +- .../formatConversionTestUtil.ts | 34 +++++++++- .../html/contextParagraph/basic.html | 10 ++- .../html/customParagraph/basic.html | 9 ++- .../html/customParagraph/lineBreaks.html | 9 ++- .../html/customParagraph/nested.html | 27 +++++++- .../html/customParagraph/styled.html | 7 +- .../__snapshots__/html/fontSize/basic.html | 7 +- .../__snapshots__/html/mention/basic.html | 7 +- .../__snapshots__/html/reactFile/basic.html | 11 ++- .../__snapshots__/html/reactFile/button.html | 8 ++- .../__snapshots__/html/reactFile/nested.html | 22 +++++- .../html/reactFile/noCaption.html | 11 ++- .../__snapshots__/html/reactFile/noName.html | 10 ++- .../__snapshots__/html/reactImage/basic.html | 5 ++ .../__snapshots__/html/reactImage/button.html | 8 ++- .../__snapshots__/html/reactImage/nested.html | 10 +++ .../html/reactImage/noCaption.html | 5 ++ .../__snapshots__/html/reactImage/noName.html | 11 ++- .../html/reactImage/noPreview.html | 5 ++ .../html/simpleCustomParagraph/basic.html | 10 ++- .../html/simpleCustomParagraph/nested.html | 30 ++++++++- .../html/simpleCustomParagraph/styled.html | 7 +- .../__snapshots__/html/small/basic.html | 7 +- .../export/__snapshots__/html/tag/basic.html | 7 +- .../exportParseEqualityTestExecutors.ts | 19 ++++++ 81 files changed, 942 insertions(+), 167 deletions(-) diff --git a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts index 61a657ed71..53333f88a3 100644 --- a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +++ b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts @@ -116,29 +116,30 @@ function serializeBlock< block.type as any ].implementation.toExternalHTML({ ...block, props } as any, editor as any); + const blockContentDataAttributes = [ + ...attrs, + ...Array.from(ret.dom.attributes), + ]; + + let listType = undefined; + if (orderedListItemBlockTypes.has(block.type!)) { + listType = "OL"; + } else if (unorderedListItemBlockTypes.has(block.type!)) { + listType = "UL"; + } + const elementFragment = doc.createDocumentFragment(); if (ret.dom.classList.contains("bn-block-content")) { - const blockContentDataAttributes = [ - ...attrs, - ...Array.from(ret.dom.attributes), - ].filter( - (attr) => - attr.name.startsWith("data") && - attr.name !== "data-content-type" && - attr.name !== "data-file-block" && - attr.name !== "data-node-view-wrapper" && - attr.name !== "data-node-type" && - attr.name !== "data-id" && - attr.name !== "data-index" && - attr.name !== "data-editable" - ); - - // ret.dom = ret.dom.firstChild! as any; - for (const attr of blockContentDataAttributes) { - (ret.dom.firstChild! as HTMLElement).setAttribute(attr.name, attr.value); + if (!listType) { + for (const attr of blockContentDataAttributes) { + (ret.dom.firstChild! as HTMLElement).setAttribute( + attr.name, + attr.value + ); + } } - addAttributesAndRemoveClasses(ret.dom.firstChild! as HTMLElement); + addAttributesAndRemoveClasses(ret.dom as HTMLElement); elementFragment.append(...Array.from(ret.dom.childNodes)); } else { elementFragment.append(ret.dom); @@ -155,13 +156,6 @@ function serializeBlock< ret.contentDOM.appendChild(ic); } - let listType = undefined; - if (orderedListItemBlockTypes.has(block.type!)) { - listType = "OL"; - } else if (unorderedListItemBlockTypes.has(block.type!)) { - listType = "UL"; - } - if (listType) { if (fragment.lastChild?.nodeName !== listType) { const list = doc.createElement(listType); @@ -172,6 +166,9 @@ function serializeBlock< fragment.append(list); } const li = doc.createElement("li"); + 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/QuoteBlockContent/QuoteBlockContent.ts b/packages/core/src/blocks/QuoteBlockContent/QuoteBlockContent.ts index a321576be0..1cd9c97b23 100644 --- a/packages/core/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +++ b/packages/core/src/blocks/QuoteBlockContent/QuoteBlockContent.ts @@ -9,7 +9,8 @@ import { updateBlockCommand } from "../../api/blockManipulation/commands/updateB import { InputRule } from "@tiptap/core"; export const quotePropSchema = { - ...defaultProps, + backgroundColor: defaultProps.backgroundColor, + textColor: defaultProps.textColor, }; export const QuoteBlockContent = createStronglyTypedTiptapNode({ diff --git a/packages/core/src/pm-nodes/BlockContainer.ts b/packages/core/src/pm-nodes/BlockContainer.ts index ecd7f8068f..2a4db957ff 100644 --- a/packages/core/src/pm-nodes/BlockContainer.ts +++ b/packages/core/src/pm-nodes/BlockContainer.ts @@ -6,8 +6,8 @@ import { mergeCSSClasses } from "../util/browser.js"; // Object containing all possible block attributes. const BlockAttributes: Record = { - blockColor: "data-block-color", - blockStyle: "data-block-style", + textColor: "data-text-color", + backgroundColor: "data-background-color", id: "data-id", depth: "data-depth", depthChange: "data-depth-change", @@ -31,7 +31,10 @@ export const BlockContainer = Node.create<{ parseHTML() { return [ { - tag: "div", + // Not only `div`s as this way props from exported HTML can also be + // parsed correctly. + tag: "*", + priority: 500, getAttrs: (element) => { if (typeof element === "string") { return false; @@ -44,12 +47,18 @@ export const BlockContainer = Node.create<{ } } - if (element.getAttribute("data-node-type") === "blockContainer") { + if ( + element.getAttribute("data-node-type") === "blockContainer" || + element.getAttribute("data-node-type") === "blockOuter" + ) { return attrs; } return false; }, + // Allows exported HTML to be parsed as both a `blockContainer` with a + // `blockContent` child, preserving all block data. + consuming: false, }, ]; }, diff --git a/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html b/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html index b0d9e1665e..cbbcb6592b 100644 --- a/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html +++ b/packages/xl-multi-column/src/test/conversions/__snapshots__/multi-column/undefined/external.html @@ -1 +1 @@ -

Column Paragraph 0

Column Paragraph 1

Column Paragraph 2

Column Paragraph 3

\ No newline at end of file +

Column Paragraph 0

Column Paragraph 1

Column Paragraph 2

Column Paragraph 3

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html index 4b0fff5d10..6f9792dd87 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html @@ -1,23 +1,54 @@ -

Paragraph 1

-

Heading 1

+

Paragraph 1

+

Heading 1

    -
  1. -

    Numbered List Item 1

    +
  2. +

    Numbered List Item 1

    -
  • -

    Bullet List Item 1

    +
  • +

    Bullet List Item 1

  • -
  • +
  • Check List Item 1

-
+
   console.log("Hello World");
 
- +

Table Cell 1

@@ -35,5 +66,16 @@

Heading 1

-

Add image

-

Paragraph 2

\ No newline at end of file +

Add image

+

Paragraph 2

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html index aa29f7463c..74b0d5e03a 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html @@ -1,23 +1,58 @@ -

Paragraph 1

-

Heading 1

+

Paragraph 1

+

Heading 1

    -
  1. -

    Numbered List Item 1

    +
  2. +

    Numbered List Item 1

    -
  • -

    Bullet List Item 1

    +
  • +

    Bullet List Item 1

  • -
  • - +
  • +

    Check List Item 1

-
+
   console.log("Hello World");
 
- +

Table Cell 1

@@ -36,10 +71,15 @@

Heading 1

Heading 1 />
Placeholder
-

Paragraph 2

\ No newline at end of file +

Paragraph 2

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childToParent.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childToParent.html index a39b61fc62..3959372fa3 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childToParent.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childToParent.html @@ -1,2 +1,12 @@ -

Paragraph 1

-

Nested Paragraph 1

\ No newline at end of file +

Paragraph 1

+

Nested Paragraph 1

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParent.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParent.html index 5482d90cfa..2ca9adb9c0 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParent.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParent.html @@ -1,4 +1,24 @@ -

Nested Paragraph 1

-

Nested Paragraph 2

-

Nested Paragraph 3

-

Paragraph 2

\ No newline at end of file +

Nested Paragraph 1

+

Nested Paragraph 2

+

Nested Paragraph 3

+

Paragraph 2

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParentsChildren.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParentsChildren.html index 5f11c91d10..5f976aeca7 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParentsChildren.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/childrenToNextParentsChildren.html @@ -1,7 +1,42 @@ -

Nested Paragraph 1

-

Nested Paragraph 2

-

Nested Paragraph 3

-

Paragraph 2

-

Nested Paragraph 4

-

Nested Paragraph 5

-

Nested Paragraph 6

\ No newline at end of file +

Nested Paragraph 1

+

Nested Paragraph 2

+

Nested Paragraph 3

+

Paragraph 2

+

Nested Paragraph 4

+

Nested Paragraph 5

+

Nested Paragraph 6

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/image.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/image.html index 3d97d675dd..ea9e878e5c 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/image.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/image.html @@ -2,5 +2,10 @@ src="https://ralfvanveen.com/wp-content/uploads/2021/06/Placeholder-_-Glossary.svg" alt="BlockNote image" width="512" + class="bn-block-content" + data-node-type="blockOuter" + data-id="1" + data-content-type="image" data-url="https://ralfvanveen.com/wp-content/uploads/2021/06/Placeholder-_-Glossary.svg" + data-file-block="" /> \ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/multipleChildren.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/multipleChildren.html index bad0f9b365..d0282c89e7 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/multipleChildren.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/multipleChildren.html @@ -1,3 +1,18 @@ -

Nested Paragraph 1

-

Nested Paragraph 2

-

Nested Paragraph 3

\ No newline at end of file +

Nested Paragraph 1

+

Nested Paragraph 2

+

Nested Paragraph 3

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/nestedImage.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/nestedImage.html index 7983b6974c..78506b13cf 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/nestedImage.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/nestedImage.html @@ -1,8 +1,23 @@ -

Paragraph 1

+

Paragraph 1

BlockNote image -

Nested Paragraph 1

\ No newline at end of file +

Nested Paragraph 1

\ No newline at end of file diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/partialChildToParent.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/partialChildToParent.html index 3599c4a943..2b9e459b54 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/partialChildToParent.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/partialChildToParent.html @@ -1,2 +1,12 @@ -

aragraph 1

-

N

\ No newline at end of file +

aragraph 1

+

N

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/contains-newlines.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/contains-newlines.html index 1b766eb380..411f5f5193 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/contains-newlines.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/contains-newlines.html @@ -1,4 +1,9 @@ -
+
   
     const hello ='world';
     
diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/defaultLanguage.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/defaultLanguage.html index c5939c1b5e..6acde9cc18 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/defaultLanguage.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/defaultLanguage.html @@ -1,3 +1,8 @@ -
+
   console.log('Hello, world!');
 
\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/empty.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/empty.html index 9bbe62c374..0c884ee5af 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/empty.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/empty.html @@ -1,3 +1,8 @@ -
+
   
 
\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/python.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/python.html index 2d95c0d45d..e69d059a33 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/python.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/codeBlock/python.html @@ -1,3 +1,8 @@ -
+
   print('Hello, world!')
 
\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/complex/misc.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/complex/misc.html index 0df8a18343..8dc11e8805 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/complex/misc.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/complex/misc.html @@ -1,4 +1,4 @@ -

+

Heading @@ -6,9 +6,20 @@

Paragraph

+

Paragraph

    -
  • -

    +
  • +

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/basic.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/basic.html index 22fe1c373a..084837640e 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/basic.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/basic.html @@ -1,4 +1,13 @@ -
+
example

Caption

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/button.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/button.html index cc675c57a7..972ad04ad6 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/button.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/button.html @@ -1 +1,7 @@ -

Add file

\ No newline at end of file +

Add file

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/nested.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/nested.html index 226ee83250..d8a4c3d197 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/nested.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/nested.html @@ -1,8 +1,26 @@ -
+
example

Caption

-
+
example

Caption

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noCaption.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noCaption.html index e1c8211b39..5566551e9c 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noCaption.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noCaption.html @@ -1 +1,10 @@ -example \ No newline at end of file +example \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noName.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noName.html index f0ac923a66..d8b2b3b396 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noName.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/file/noName.html @@ -1,4 +1,12 @@ -
+
exampleURL

Caption

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/basic.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/basic.html index d0444869cc..9b427c4012 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/basic.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/basic.html @@ -1,4 +1,9 @@ -

+

Text1
Text2 diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/between-links.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/between-links.html index 701b5d4213..41e07850fa 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/between-links.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/between-links.html @@ -1,4 +1,9 @@ -

+

+

Text1

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/link.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/link.html index 2c762aedc5..0c47cf456d 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/link.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/link.html @@ -1,4 +1,9 @@ -

+

+

Text1
Text2 diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/only.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/only.html index b96f89d7a0..d5dec474fa 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/only.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/only.html @@ -1,3 +1,8 @@ -

+


\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/start.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/start.html index f0370a6c68..50f18ae52a 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/start.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/start.html @@ -1,4 +1,9 @@ -

+


Text1

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/styles.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/styles.html index 7a49318b49..38b4c9556c 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/styles.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/hardbreak/styles.html @@ -1,4 +1,9 @@ -

+

Text1
Text2 diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/basic.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/basic.html index 59f782dbb1..7ac6e5f834 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/basic.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/basic.html @@ -1,8 +1,13 @@

example

Caption

diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/button.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/button.html index 8553433aff..7799f53c85 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/button.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/button.html @@ -1 +1,7 @@ -

Add image

\ No newline at end of file +

Add image

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/nested.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/nested.html index 8cc825084e..37970c2ff4 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/nested.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/nested.html @@ -1,8 +1,26 @@ -
+
exampleURL

Caption

-
+
exampleURL

Caption

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noCaption.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noCaption.html index 269bdeca7e..756b162537 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noCaption.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noCaption.html @@ -1,6 +1,11 @@ example \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noName.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noName.html index decd178fbe..68d8e2d5c5 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noName.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noName.html @@ -1,4 +1,13 @@ -
+
exampleURL

Caption

\ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noPreview.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noPreview.html index 21bf2faaf1..299010b13e 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noPreview.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/image/noPreview.html @@ -1,9 +1,14 @@
example

Caption

diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/link/adjacent.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/link/adjacent.html index db99691d33..c8323855e6 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/link/adjacent.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/link/adjacent.html @@ -1,4 +1,9 @@ -

+

+

+

-

  • -

    Bullet List Item 1

    +
  • +

    Bullet List Item 1

  • -
  • -

    Bullet List Item 2

    +
  • +

    Bullet List Item 2

    1. -
    2. -

      Numbered List Item 1

      +
    3. +

      Numbered List Item 1

    4. -
    5. -

      Numbered List Item 2

      +
    6. +

      Numbered List Item 2

      -
    • +
    • Check List Item 1

    • -
    • - +
    • +

      Check List Item 2

    \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html index b2497ae937..b87f0e62f5 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html @@ -1,22 +1,55 @@