Skip to content

Commit f629634

Browse files
fix: External HTML parse/export cases cont. (#1998)
* Added plugin for collab schema migration * Moved color props to block content nodes * Fixed export for list items and updated unit test snapshots * Rename * Updated test snapshots * Implemented PR feedback * Fixed build
1 parent a70dbce commit f629634

File tree

212 files changed

+2376
-2193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+2376
-2193
lines changed

packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,7 @@ function serializeBlock<
232232
}
233233
fragment.append(list);
234234
}
235-
const li = doc.createElement("li");
236-
li.append(elementFragment);
237-
fragment.lastChild!.appendChild(li);
235+
fragment.lastChild!.appendChild(elementFragment);
238236
} else {
239237
fragment.append(elementFragment);
240238
}

packages/core/src/blocks/ListItem/BulletListItem/block.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,14 @@ export const createBulletListItemBlockSpec = createBlockSpec(
6565
};
6666
},
6767
toExternalHTML(block) {
68-
const dom = document.createElement("p");
69-
addDefaultPropsExternalHTML(block.props, dom);
68+
const li = document.createElement("li");
69+
const p = document.createElement("p");
70+
addDefaultPropsExternalHTML(block.props, li);
71+
li.appendChild(p);
7072

7173
return {
72-
dom,
73-
contentDOM: dom,
74+
dom: li,
75+
contentDOM: p,
7476
};
7577
},
7678
},

packages/core/src/blocks/ListItem/CheckListItem/block.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,17 @@ export const createCheckListItemBlockSpec = createBlockSpec(
7373
// into a single one so that ProseMirror can parse everything correctly.
7474
parseContent: ({ el, schema }) =>
7575
getListItemContent(el, schema, "checkListItem"),
76-
render(block) {
76+
render(block, editor) {
7777
const dom = document.createDocumentFragment();
7878
const checkbox = document.createElement("input");
7979
checkbox.type = "checkbox";
8080
checkbox.checked = block.props.checked;
8181
if (block.props.checked) {
8282
checkbox.setAttribute("checked", "");
8383
}
84+
checkbox.addEventListener("change", () => {
85+
editor.updateBlock(block, { props: { checked: !block.props.checked } });
86+
});
8487
// We use a <p> tag, because for <li> tags we'd need a <ul> element to put
8588
// them in to be semantically correct, which we can't have due to the
8689
// schema.
@@ -95,7 +98,7 @@ export const createCheckListItemBlockSpec = createBlockSpec(
9598
};
9699
},
97100
toExternalHTML(block) {
98-
const dom = document.createDocumentFragment();
101+
const dom = document.createElement("li");
99102
const checkbox = document.createElement("input");
100103
checkbox.type = "checkbox";
101104
checkbox.checked = block.props.checked;
@@ -106,7 +109,7 @@ export const createCheckListItemBlockSpec = createBlockSpec(
106109
// them in to be semantically correct, which we can't have due to the
107110
// schema.
108111
const paragraph = document.createElement("p");
109-
addDefaultPropsExternalHTML(block.props, paragraph);
112+
addDefaultPropsExternalHTML(block.props, dom);
110113

111114
dom.appendChild(checkbox);
112115
dom.appendChild(paragraph);

packages/core/src/blocks/ListItem/NumberedListItem/block.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ export const createNumberedListItemBlockSpec = createBlockSpec(
7878
};
7979
},
8080
toExternalHTML(block) {
81-
const dom = document.createElement("p");
82-
addDefaultPropsExternalHTML(block.props, dom);
81+
const li = document.createElement("li");
82+
const p = document.createElement("p");
83+
addDefaultPropsExternalHTML(block.props, li);
84+
li.appendChild(p);
8385

8486
return {
85-
dom,
86-
contentDOM: dom,
87+
dom: li,
88+
contentDOM: p,
8789
};
8890
},
8991
},

packages/core/src/blocks/ListItem/ToggleListItem/block.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,15 @@ export const createToggleListItemBlockSpec = createBlockSpec(
3838
return { ...toggleWrapper, contentDOM: paragraphEl };
3939
},
4040
toExternalHTML(block) {
41-
const paragraphEl = document.createElement("p");
42-
addDefaultPropsExternalHTML(block.props, paragraphEl);
43-
return { dom: paragraphEl, contentDOM: paragraphEl };
41+
const li = document.createElement("li");
42+
const p = document.createElement("p");
43+
addDefaultPropsExternalHTML(block.props, li);
44+
li.appendChild(p);
45+
46+
return {
47+
dom: li,
48+
contentDOM: p,
49+
};
4450
},
4551
},
4652
[

packages/core/src/blocks/defaultProps.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,27 @@ export const defaultProps = {
2121

2222
export type DefaultProps = Props<typeof defaultProps>;
2323

24-
// Default props which are set on `blockContainer` nodes rather than
25-
// `blockContent` nodes. Ensures that they are not redundantly added to
26-
// a custom block's TipTap node attributes.
27-
export const inheritedProps = ["backgroundColor", "textColor"];
28-
29-
// TODO: Move text/background color props from `blockContainer` node to
30-
// `blockContent`.
3124
export const parseDefaultProps = (element: HTMLElement) => {
3225
const props: Partial<DefaultProps> = {};
3326

27+
// If the `data-` attribute is found, set the prop to the value, as this most
28+
// likely means the parsed element was exported by BlockNote originally.
29+
// Otherwise, just use whatever is found in the inline styles, if anything.
30+
if (element.hasAttribute("data-background-color")) {
31+
props.backgroundColor = element.getAttribute("data-background-color")!;
32+
} else if (element.style.backgroundColor) {
33+
props.backgroundColor = element.style.backgroundColor;
34+
}
35+
36+
// If the `data-` attribute is found, set the prop to the value, as this most
37+
// likely means the parsed element was exported by BlockNote originally.
38+
// Otherwise, just use whatever is found in the inline styles, if anything.
39+
if (element.hasAttribute("data-text-color")) {
40+
props.textColor = element.getAttribute("data-text-color")!;
41+
} else if (element.style.color) {
42+
props.textColor = element.style.color;
43+
}
44+
3445
props.textAlignment = defaultProps.textAlignment.values.includes(
3546
element.style.textAlign as DefaultProps["textAlignment"],
3647
)
@@ -48,27 +59,23 @@ export const addDefaultPropsExternalHTML = (
4859
props.backgroundColor &&
4960
props.backgroundColor !== defaultProps.backgroundColor.default
5061
) {
51-
if (props.backgroundColor in COLORS_DEFAULT) {
52-
element.style.setProperty(
53-
`--blocknote-background-${props.backgroundColor}`,
54-
COLORS_DEFAULT[props.backgroundColor].background,
55-
);
56-
element.style.backgroundColor = `var(--blocknote-background-${props.backgroundColor})`;
57-
} else {
58-
element.style.backgroundColor = props.backgroundColor;
59-
}
62+
// The color can be any string. If the string matches one of the default
63+
// theme color names, set the theme color. Otherwise, set the color as-is
64+
// (may be a CSS color name, hex value, RGB value, etc).
65+
element.style.backgroundColor =
66+
props.backgroundColor in COLORS_DEFAULT
67+
? COLORS_DEFAULT[props.backgroundColor].background
68+
: props.backgroundColor;
6069
}
6170

6271
if (props.textColor && props.textColor !== defaultProps.textColor.default) {
63-
if (props.textColor in COLORS_DEFAULT) {
64-
element.style.setProperty(
65-
`--blocknote-text-${props.textColor}`,
66-
COLORS_DEFAULT[props.textColor].text,
67-
);
68-
element.style.color = `var(--blocknote-text-${props.textColor})`;
69-
} else {
70-
element.style.color = props.textColor;
71-
}
72+
// The color can be any string. If the string matches one of the default
73+
// theme color names, set the theme color. Otherwise, set the color as-is
74+
// (may be a CSS color name, hex value, RGB value, etc).
75+
element.style.color =
76+
props.textColor in COLORS_DEFAULT
77+
? COLORS_DEFAULT[props.textColor].text
78+
: props.textColor;
7279
}
7380

7481
if (

packages/core/src/editor/Block.css

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -559,76 +559,94 @@ NESTED BLOCKS
559559
/* TODO: should this be here? */
560560

561561
/* TEXT COLORS */
562-
[data-text-color="gray"] {
562+
[data-text-color="gray"],
563+
.bn-block:has(> .bn-block-content[data-text-color="gray"]) {
563564
color: #9b9a97;
564565
}
565566

566-
[data-text-color="brown"] {
567+
[data-text-color="brown"],
568+
.bn-block:has(> .bn-block-content[data-text-color="brown"]) {
567569
color: #64473a;
568570
}
569571

570-
[data-text-color="red"] {
572+
[data-text-color="red"],
573+
.bn-block:has(> .bn-block-content[data-text-color="red"]) {
571574
color: #e03e3e;
572575
}
573576

574-
[data-text-color="orange"] {
577+
[data-text-color="orange"],
578+
.bn-block:has(> .bn-block-content[data-text-color="orange"]) {
575579
color: #d9730d;
576580
}
577581

578-
[data-text-color="yellow"] {
582+
[data-text-color="yellow"],
583+
.bn-block:has(> .bn-block-content[data-text-color="yellow"]) {
579584
color: #dfab01;
580585
}
581586

582-
[data-text-color="green"] {
587+
[data-text-color="green"],
588+
.bn-block:has(> .bn-block-content[data-text-color="green"]) {
583589
color: #4d6461;
584590
}
585591

586-
[data-text-color="blue"] {
592+
[data-text-color="blue"],
593+
.bn-block:has(> .bn-block-content[data-text-color="blue"]) {
587594
color: #0b6e99;
588595
}
589596

590-
[data-text-color="purple"] {
597+
[data-text-color="purple"],
598+
.bn-block:has(> .bn-block-content[data-text-color="purple"]) {
591599
color: #6940a5;
592600
}
593601

594-
[data-text-color="pink"] {
602+
[data-text-color="pink"],
603+
.bn-block:has(> .bn-block-content[data-text-color="pink"]) {
595604
color: #ad1a72;
596605
}
597606

598607
/* BACKGROUND COLORS */
599-
[data-background-color="gray"] {
608+
[data-background-color="gray"],
609+
.bn-block:has(> .bn-block-content[data-background-color="gray"]) {
600610
background-color: #ebeced;
601611
}
602612

603-
[data-background-color="brown"] {
613+
[data-background-color="brown"],
614+
.bn-block:has(> .bn-block-content[data-background-color="brown"]) {
604615
background-color: #e9e5e3;
605616
}
606617

607-
[data-background-color="red"] {
618+
[data-background-color="red"],
619+
.bn-block:has(> .bn-block-content[data-background-color="red"]) {
608620
background-color: #fbe4e4;
609621
}
610622

611-
[data-background-color="orange"] {
623+
[data-background-color="orange"],
624+
.bn-block:has(> .bn-block-content[data-background-color="orange"]) {
612625
background-color: #f6e9d9;
613626
}
614627

615-
[data-background-color="yellow"] {
628+
[data-background-color="yellow"],
629+
.bn-block:has(> .bn-block-content[data-background-color="yellow"]) {
616630
background-color: #fbf3db;
617631
}
618632

619-
[data-background-color="green"] {
633+
[data-background-color="green"],
634+
.bn-block:has(> .bn-block-content[data-background-color="green"]) {
620635
background-color: #ddedea;
621636
}
622637

623-
[data-background-color="blue"] {
638+
[data-background-color="blue"],
639+
.bn-block:has(> .bn-block-content[data-background-color="blue"]) {
624640
background-color: #ddebf1;
625641
}
626642

627-
[data-background-color="purple"] {
643+
[data-background-color="purple"],
644+
.bn-block:has(> .bn-block-content[data-background-color="purple"]) {
628645
background-color: #eae4f2;
629646
}
630647

631-
[data-background-color="pink"] {
648+
[data-background-color="pink"],
649+
.bn-block:has(> .bn-block-content[data-background-color="pink"]) {
632650
background-color: #f4dfeb;
633651
}
634652

packages/core/src/editor/BlockNoteEditor.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@ export class BlockNoteEditor<
571571
headers: boolean;
572572
};
573573
};
574-
575574
public static create<
576575
Options extends Partial<BlockNoteEditorOptions<any, any, any>> | undefined,
577576
>(

packages/core/src/editor/BlockNoteExtensions.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import type { ThreadStore } from "../comments/index.js";
1313
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension.js";
1414
import { BlockChangePlugin } from "../extensions/BlockChange/BlockChangePlugin.js";
1515
import { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
16+
import { ForkYDocPlugin } from "../extensions/Collaboration/ForkYDocPlugin.js";
1617
import { SyncPlugin } from "../extensions/Collaboration/SyncPlugin.js";
1718
import { UndoPlugin } from "../extensions/Collaboration/UndoPlugin.js";
19+
import { SchemaMigrationPlugin } from "../extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.js";
1820
import { CommentMark } from "../extensions/Comments/CommentMark.js";
1921
import { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
2022
import { FilePanelProsemirrorPlugin } from "../extensions/FilePanel/FilePanelPlugin.js";
@@ -58,7 +60,6 @@ import type {
5860
SupportedExtension,
5961
} from "./BlockNoteEditor.js";
6062
import { BlockNoteSchema } from "../blocks/BlockNoteSchema.js";
61-
import { ForkYDocPlugin } from "../extensions/Collaboration/ForkYDocPlugin.js";
6263

6364
type ExtensionOptions<
6465
BSchema extends BlockSchema,
@@ -127,6 +128,9 @@ export const getBlockNoteExtensions = <
127128
editor: opts.editor,
128129
collaboration: opts.collaboration,
129130
});
131+
ret["schemaMigrationPlugin"] = new SchemaMigrationPlugin(
132+
opts.collaboration.fragment,
133+
);
130134
}
131135

132136
// Note: this is pretty hardcoded and will break when user provides plugins with same keys.

packages/core/src/extensions/BackgroundColor/BackgroundColorExtension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const BackgroundColorExtension = Extension.create({
77
addGlobalAttributes() {
88
return [
99
{
10-
types: ["blockContainer", "tableCell", "tableHeader"],
10+
types: ["tableCell", "tableHeader"],
1111
attributes: {
1212
backgroundColor: getBackgroundColorAttribute(),
1313
},

0 commit comments

Comments
 (0)