Skip to content

Commit 8fbd7e0

Browse files
fix: table column widths not being set in exported HTML (#1947)
1 parent 5354347 commit 8fbd7e0

File tree

22 files changed

+131
-16
lines changed

22 files changed

+131
-16
lines changed

docs/content/docs/features/export/html.mdx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ path: /docs/converting-blocks
1616

1717
## Export to BlockNote HTML
1818

19-
Use `editor.blocksToFullHTML` to export the entire document with all structure, styles and formatting.
20-
The exported HTML is the same as BlockNote would use to render the editor, and includes all structure for nested blocks.
19+
Use `editor.blocksToFullHTML` to export blocks with their full HTML structure, the same as BlockNote uses in its rendered HTML.
2120

2221
For example, you an use this for static rendering documents that have been created in the editor.
23-
Make sure to include the same stylesheets when you want to render the output HTML ([see example](/examples/backend/rendering-static-documents)).
22+
23+
<Callout type={"info"}>
24+
For the exported HTML to look the same as the editor, make sure to wrap it in the same `div`s that the editor renders, and add the same stylesheets. To learn more, see [this example](/examples/backend/rendering-static-documents).
25+
26+
</Callout>
2427

2528
```typescript
2629
async blocksToFullHTML(blocks?: Block[]): Promise<string>;

examples/02-backend/04-rendering-static-documents/src/App.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import "@blocknote/core/fonts/inter.css";
2-
import "@blocknote/core/style.css";
2+
import "@blocknote/mantine/style.css";
33

44
/**
55
On Server Side, you can use the ServerBlockNoteEditor to render BlockNote documents to HTML. e.g.:
66
7-
import { ServerBlockNoteEditor } from "@blocknote/server-util";
7+
import { ServerBlockNoteEditor } from "@blocknote/server-util";
88
9-
const editor = ServerBlockNoteEditor.create();
10-
const html = await editor.blocksToFullHTML(document);
9+
const editor = ServerBlockNoteEditor.create();
10+
const html = await editor.blocksToFullHTML(document);
1111
1212
You can then use render this HTML as a static page or send it to the client. Make sure to include the editor stylesheets:
13-
14-
import "@blocknote/core/fonts/inter.css";
15-
import "@blocknote/core/style.css";
13+
14+
import "@blocknote/core/fonts/inter.css";
15+
// Depending on the UI library you're using, you may want to use `react`,
16+
// `mantine`, etc instead of `core`.
17+
import "@blocknote/core/style.css";
1618
1719
This example has the HTML hard-coded, but shows at least how the document will be rendered when the appropriate style sheets are loaded.
1820
*/
@@ -50,9 +52,14 @@ export default function App() {
5052

5153
// Renders the editor instance using a React component.
5254
return (
53-
<div className="bn-container">
55+
// To make the HTML look identical to the editor, we need to add these two
56+
// wrapping divs to the exported blocks. You need will need to add
57+
// additional class names/attributes depend on the UI library you're using,
58+
// whether you want to show light or dark more, etc. It's easiest to just
59+
// check the rendered editor HTML to see what you need to add.
60+
<div className="bn-container bn-mantine">
5461
<div
55-
className="bn-default-styles"
62+
className="ProseMirror bn-editor bn-default-styles"
5663
dangerouslySetInnerHTML={{ __html: html }}
5764
/>
5865
</div>

packages/core/src/blocks/TableBlockContent/TableBlockContent.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export const TableBlockContent = createStronglyTypedTiptapNode({
3434
];
3535
},
3636

37-
renderHTML({ HTMLAttributes }) {
38-
return createDefaultBlockDOMOutputSpec(
37+
renderHTML({ node, HTMLAttributes }) {
38+
const domOutputSpec = createDefaultBlockDOMOutputSpec(
3939
this.name,
4040
"table",
4141
{
@@ -44,6 +44,30 @@ export const TableBlockContent = createStronglyTypedTiptapNode({
4444
},
4545
this.options.domAttributes?.inlineContent || {},
4646
);
47+
48+
// Need to manually add colgroup element
49+
const colGroup = document.createElement("colgroup");
50+
for (const tableCell of node.children[0].children) {
51+
const colWidths: null | (number | undefined)[] =
52+
tableCell.attrs["colwidth"];
53+
54+
if (colWidths) {
55+
for (const colWidth of tableCell.attrs["colwidth"]) {
56+
const col = document.createElement("col");
57+
if (colWidth) {
58+
col.style = `width: ${colWidth}px`;
59+
}
60+
61+
colGroup.appendChild(col);
62+
}
63+
} else {
64+
colGroup.appendChild(document.createElement("col"));
65+
}
66+
}
67+
68+
domOutputSpec.dom.firstChild?.appendChild(colGroup);
69+
70+
return domOutputSpec;
4771
},
4872

4973
// This node view is needed for the `columnResizing` plugin. By default, the
@@ -146,8 +170,11 @@ const TableParagraph = createStronglyTypedTiptapNode({
146170
];
147171
},
148172

149-
renderHTML({ HTMLAttributes }) {
150-
return ["p", HTMLAttributes, 0];
173+
renderHTML({ node, HTMLAttributes }) {
174+
// Insert a line break if there is no content, in order to preserve the
175+
// correct cell height. Otherwise, the cell will have a height of zero +
176+
// padding.
177+
return ["p", HTMLAttributes, node.childCount ? 0 : ["br"]];
151178
},
152179
});
153180

35 Bytes
Loading
153 Bytes
Loading
46 Bytes
Loading

tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ <h1>Heading 1</h1>
1818
<code class="bn-inline-content language-text" data-language="text">console.log("Hello World");</code>
1919
</pre>
2020
<table>
21+
<colgroup>
22+
<col />
23+
<col />
24+
</colgroup>
2125
<tr>
2226
<td colspan="1" rowspan="1">
2327
<p>Table Cell 1</p>

tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ <h2 data-level="2">Heading 1</h2>
1818
<code class="bn-inline-content language-typescript" data-language="typescript">console.log("Hello World");</code>
1919
</pre>
2020
<table>
21+
<colgroup>
22+
<col />
23+
<col />
24+
</colgroup>
2125
<tr>
2226
<td colspan="1" rowspan="1">
2327
<p>Table Cell 1</p>

tests/src/unit/core/formatConversion/export/__snapshots__/blocknoteHTML/table/allColWidths.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
<div class="bn-block" data-node-type="blockContainer" data-id="1">
44
<div class="bn-block-content" data-content-type="table">
55
<table class="bn-inline-content">
6+
<colgroup>
7+
<col style="width: 100px;" />
8+
<col style="width: 200px;" />
9+
<col style="width: 300px;" />
10+
</colgroup>
611
<tr>
712
<td colspan="1" rowspan="1" colwidth="100">
813
<p>Table Cell</p>

tests/src/unit/core/formatConversion/export/__snapshots__/blocknoteHTML/table/basic.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
<div class="bn-block" data-node-type="blockContainer" data-id="1">
44
<div class="bn-block-content" data-content-type="table">
55
<table class="bn-inline-content">
6+
<colgroup>
7+
<col />
8+
<col />
9+
<col />
10+
</colgroup>
611
<tr>
712
<td colspan="1" rowspan="1">
813
<p>Table Cell</p>

0 commit comments

Comments
 (0)