Skip to content

feat: Better parsing of external HTML attributes & inline styles #1605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
17 changes: 13 additions & 4 deletions packages/core/src/pm-nodes/BlockContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { mergeCSSClasses } from "../util/browser.js";

// Object containing all possible block attributes.
const BlockAttributes: Record<string, string> = {
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",
Expand All @@ -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;
Expand All @@ -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,
},
];
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div class="bn-block-column-list" data-node-type="columnList" data-id="1" style="display: flex;"><div class="bn-block-column" data-node-type="column" data-id="2" data-width="1" style="flex-grow: 1;"><p class="bn-block-content" data-node-type="blockOuter" data-id="3" data-content-type="paragraph">Column Paragraph 0</p><p class="bn-block-content" data-node-type="blockOuter" data-id="4" data-content-type="paragraph">Column Paragraph 1</p></div><div class="bn-block-column" data-node-type="column" data-id="5" data-width="1" style="flex-grow: 1;"><p class="bn-block-content" data-node-type="blockOuter" data-id="6" data-content-type="paragraph">Column Paragraph 2</p><p class="bn-block-content" data-node-type="blockOuter" data-id="7" data-content-type="paragraph">Column Paragraph 3</p></div></div>
<div class="bn-block-column-list" data-node-type="columnList" data-id="1" style="display: flex;"><div class="bn-block-column" data-node-type="column" data-id="2" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 0</p><p>Column Paragraph 1</p></div><div class="bn-block-column" data-node-type="column" data-id="5" data-width="1" style="flex-grow: 1;"><p>Column Paragraph 2</p><p>Column Paragraph 3</p></div></div>
Original file line number Diff line number Diff line change
@@ -1,23 +1,54 @@
<p>Paragraph 1</p>
<h1>Heading 1</h1>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="1"
data-content-type="paragraph"
>Paragraph 1</p>
<h1 class="bn-block-content" data-node-type="blockOuter" data-id="2" data-content-type="heading">Heading 1</h1>
<ol>
<li>
<p>Numbered List Item 1</p>
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="3"
data-content-type="numberedListItem"
data-index="null"
>
<p class="bn-inline-content">Numbered List Item 1</p>
</li>
</ol>
<ul>
<li>
<p>Bullet List Item 1</p>
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="4"
data-content-type="bulletListItem"
>
<p class="bn-inline-content">Bullet List Item 1</p>
</li>
<li>
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="5"
data-content-type="checkListItem"
>
<input type="checkbox" />
<p class="bn-inline-content">Check List Item 1</p>
</li>
</ul>
<pre>
<pre
class="bn-block-content"
data-node-type="blockOuter"
data-id="6"
data-content-type="codeBlock"
>
<code class="bn-inline-content language-text" data-language="text">console.log("Hello World");</code>
</pre>
<table>
<table
class="bn-block-content"
data-node-type="blockOuter"
data-id="7"
data-content-type="table"
>
<tr>
<td colspan="1" rowspan="1">
<p>Table Cell 1</p>
Expand All @@ -35,5 +66,16 @@ <h1>Heading 1</h1>
</td>
</tr>
</table>
<p>Add image</p>
<p>Paragraph 2</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="8"
data-content-type="image"
data-file-block=""
>Add image</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="9"
data-content-type="paragraph"
>Paragraph 2</p>
Original file line number Diff line number Diff line change
@@ -1,23 +1,58 @@
<p data-text-color="red">Paragraph 1</p>
<h2 data-level="2">Heading 1</h2>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="1"
data-text-color="red"
data-content-type="paragraph"
>Paragraph 1</p>
<h2 class="bn-block-content" data-node-type="blockOuter" data-id="2" data-content-type="heading" data-level="2">Heading 1</h2>
<ol start="2">
<li>
<p data-start="2">Numbered List Item 1</p>
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="3"
data-content-type="numberedListItem"
data-start="2"
data-index="null"
>
<p class="bn-inline-content">Numbered List Item 1</p>
</li>
</ol>
<ul>
<li>
<p data-background-color="red">Bullet List Item 1</p>
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="4"
data-background-color="red"
data-content-type="bulletListItem"
>
<p class="bn-inline-content">Bullet List Item 1</p>
</li>
<li>
<input type="checkbox" checked="" data-checked="true" />
<li
class="bn-block-content"
data-node-type="blockOuter"
data-id="5"
data-content-type="checkListItem"
data-checked="true"
>
<input type="checkbox" checked="" />
<p class="bn-inline-content">Check List Item 1</p>
</li>
</ul>
<pre>
<pre
class="bn-block-content"
data-node-type="blockOuter"
data-id="6"
data-content-type="codeBlock"
>
<code class="bn-inline-content language-typescript" data-language="typescript">console.log("Hello World");</code>
</pre>
<table>
<table
class="bn-block-content"
data-node-type="blockOuter"
data-id="7"
data-content-type="table"
>
<tr>
<td colspan="1" rowspan="1">
<p>Table Cell 1</p>
Expand All @@ -36,10 +71,15 @@ <h2 data-level="2">Heading 1</h2>
</tr>
</table>
<figure
class="bn-block-content"
data-node-type="blockOuter"
data-id="8"
data-content-type="image"
data-name="1280px-Placeholder_view_vector.svg.png"
data-url="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Placeholder_view_vector.svg/1280px-Placeholder_view_vector.svg.png"
data-caption="Placeholder"
data-preview-width="256"
data-file-block=""
>
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Placeholder_view_vector.svg/1280px-Placeholder_view_vector.svg.png"
Expand All @@ -48,4 +88,9 @@ <h2 data-level="2">Heading 1</h2>
/>
<figcaption>Placeholder</figcaption>
</figure>
<p>Paragraph 2</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="9"
data-content-type="paragraph"
>Paragraph 2</p>
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
<p>Paragraph 1</p>
<p>Nested Paragraph 1</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="1"
data-content-type="paragraph"
>Paragraph 1</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="2"
data-content-type="paragraph"
>Nested Paragraph 1</p>
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
<p>Nested Paragraph 1</p>
<p>Nested Paragraph 2</p>
<p>Nested Paragraph 3</p>
<p>Paragraph 2</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="2"
data-content-type="paragraph"
>Nested Paragraph 1</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="3"
data-content-type="paragraph"
>Nested Paragraph 2</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="4"
data-content-type="paragraph"
>Nested Paragraph 3</p>
<p
class="bn-block-content"
data-node-type="blockOuter"
data-id="5"
data-content-type="paragraph"
>Paragraph 2</p>
Loading
Loading