diff --git a/examples/05-interoperability/05-converting-blocks-to-pdf/App.tsx b/examples/05-interoperability/05-converting-blocks-to-pdf/App.tsx
index 269cc81c9a..a163fa1c8b 100644
--- a/examples/05-interoperability/05-converting-blocks-to-pdf/App.tsx
+++ b/examples/05-interoperability/05-converting-blocks-to-pdf/App.tsx
@@ -29,6 +29,12 @@ export default function App() {
// Creates a new editor instance with some initial content.
const editor = useCreateBlockNote({
schema: withPageBreak(BlockNoteSchema.create()),
+ tables: {
+ splitCells: true,
+ cellBackgroundColor: true,
+ cellTextColor: true,
+ headers: true,
+ },
initialContent: [
{
type: "paragraph",
diff --git a/examples/05-interoperability/06-converting-blocks-to-docx/App.tsx b/examples/05-interoperability/06-converting-blocks-to-docx/App.tsx
index 94bb8d8c91..9ab9a0b0de 100644
--- a/examples/05-interoperability/06-converting-blocks-to-docx/App.tsx
+++ b/examples/05-interoperability/06-converting-blocks-to-docx/App.tsx
@@ -25,6 +25,12 @@ export default function App() {
// Creates a new editor instance with some initial content.
const editor = useCreateBlockNote({
schema: withPageBreak(BlockNoteSchema.create()),
+ tables: {
+ splitCells: true,
+ cellBackgroundColor: true,
+ cellTextColor: true,
+ headers: true,
+ },
initialContent: [
{
type: "paragraph",
diff --git a/packages/xl-docx-exporter/src/docx/__snapshots__/basic/document.xml b/packages/xl-docx-exporter/src/docx/__snapshots__/basic/document.xml
index ccd1ff2147..15e743e52e 100644
--- a/packages/xl-docx-exporter/src/docx/__snapshots__/basic/document.xml
+++ b/packages/xl-docx-exporter/src/docx/__snapshots__/basic/document.xml
@@ -292,6 +292,7 @@
+
@@ -300,6 +301,9 @@
+
+
+
Table Cell
@@ -307,6 +311,9 @@
+
+
+
Table Cell
@@ -318,6 +325,7 @@
+
@@ -326,6 +334,9 @@
+
+
+
Table Cell
@@ -333,6 +344,9 @@
+
+
+
Table Cell
@@ -344,6 +358,7 @@
+
@@ -352,6 +367,9 @@
+
+
+
Table Cell
@@ -359,6 +377,9 @@
+
+
+
Table Cell
@@ -599,6 +620,9 @@
+
+
+
Table Cell 1
@@ -606,6 +630,9 @@
+
+
+
Table Cell 2
@@ -613,6 +640,9 @@
+
+
+
Table Cell 3
@@ -622,6 +652,9 @@
+
+
+
Table Cell 4
@@ -629,6 +662,9 @@
+
+
+
@@ -640,6 +676,9 @@
+
+
+
Table Cell 6
@@ -649,6 +688,9 @@
+
+
+
Table Cell 7
@@ -656,6 +698,9 @@
+
+
+
Table Cell 8
@@ -663,6 +708,9 @@
+
+
+
Table Cell 9
diff --git a/packages/xl-docx-exporter/src/docx/util/Table.tsx b/packages/xl-docx-exporter/src/docx/util/Table.tsx
index 71db4f24af..9d1e084fdc 100644
--- a/packages/xl-docx-exporter/src/docx/util/Table.tsx
+++ b/packages/xl-docx-exporter/src/docx/util/Table.tsx
@@ -1,8 +1,15 @@
-import { Exporter, InlineContentSchema, TableContent } from "@blocknote/core";
+import {
+ Exporter,
+ InlineContentSchema,
+ mapTableCell,
+ TableContent,
+ UnreachableCaseError,
+} from "@blocknote/core";
import {
Table as DocxTable,
Paragraph,
ParagraphChild,
+ ShadingType,
TableCell,
TableRow,
} from "docx";
@@ -12,33 +19,84 @@ export const Table = (
t: Exporter
) => {
const DEFAULT_COLUMN_WIDTH = 120;
+
+ // If headerRows is 1, then the first row is a header row
+ const headerRows = new Array(data.headerRows ?? 0).fill(true);
+ // If headerCols is 1, then the first column is a header column
+ const headerCols = new Array(data.headerCols ?? 0).fill(true);
+
return new DocxTable({
layout: "autofit",
columnWidths: data.columnWidths.map(
(w) =>
(w ?? DEFAULT_COLUMN_WIDTH) * /* to points */ 0.75 * /* to twips */ 20
),
- rows: data.rows.map(
- (row) =>
- new TableRow({
- children: row.cells.map((cell, i) => {
- const width = data.columnWidths?.[i];
- return new TableCell({
- width: width
- ? {
- size: `${width * 0.75}pt`,
- type: "dxa",
- }
- : undefined,
- children: [
- new Paragraph({
- // TODO: fix this
- children: t.transformInlineContent(cell as any),
- }),
- ],
- });
- }),
- })
- ),
+ rows: data.rows.map((row, rowIndex) => {
+ const isHeaderRow = headerRows[rowIndex];
+ return new TableRow({
+ tableHeader: isHeaderRow,
+ children: row.cells.map((c, colIndex) => {
+ const width = data.columnWidths?.[colIndex];
+ const cell = mapTableCell(c);
+ const isHeaderColumn = headerCols[colIndex];
+
+ return new TableCell({
+ width: width
+ ? {
+ size: `${width * 0.75}pt`,
+ type: "dxa",
+ }
+ : undefined,
+ columnSpan: cell.props.colspan,
+ rowSpan: cell.props.rowspan,
+ shading:
+ cell.props.backgroundColor === "default" ||
+ !cell.props.backgroundColor
+ ? undefined
+ : {
+ type: ShadingType.SOLID,
+ color:
+ t.options.colors[
+ cell.props
+ .backgroundColor as keyof typeof t.options.colors
+ ].background.slice(1),
+ },
+ children: [
+ new Paragraph({
+ children: t.transformInlineContent(cell.content),
+
+ alignment:
+ !cell.props.textAlignment ||
+ cell.props.textAlignment === "left"
+ ? undefined
+ : cell.props.textAlignment === "center"
+ ? "center"
+ : cell.props.textAlignment === "right"
+ ? "right"
+ : cell.props.textAlignment === "justify"
+ ? "distribute"
+ : (() => {
+ throw new UnreachableCaseError(
+ cell.props.textAlignment
+ );
+ })(),
+ run: {
+ // TODO add support for table headers exporting, bolding seems to not be working at the moment
+ bold: isHeaderRow || isHeaderColumn,
+ // TODO table paragraph color seems to not be working at the moment
+ // Probably because the runs are setting their own color
+ color:
+ cell.props.textColor === "default" || !cell.props.textColor
+ ? undefined
+ : t.options.colors[
+ cell.props.textColor as keyof typeof t.options.colors
+ ].text.slice(1),
+ },
+ }),
+ ],
+ });
+ }),
+ });
+ }),
});
};
diff --git a/packages/xl-pdf-exporter/src/pdf/util/table/Table.tsx b/packages/xl-pdf-exporter/src/pdf/util/table/Table.tsx
index 56991d330d..f7c5ef03b5 100644
--- a/packages/xl-pdf-exporter/src/pdf/util/table/Table.tsx
+++ b/packages/xl-pdf-exporter/src/pdf/util/table/Table.tsx
@@ -30,6 +30,9 @@ const styles = StyleSheet.create({
wordWrap: "break-word",
whiteSpace: "pre-wrap",
},
+ headerCell: {
+ fontWeight: "bold",
+ },
bottomCell: {
borderBottom: "1px solid #ddd",
},
@@ -49,31 +52,62 @@ export const Table = (props: {
any,
any
>;
-}) => (
-
- {props.data.rows.map((row, index) => (
-
- {row.cells.map((cell, index) => (
-
- {props.transformer.transformInlineContent(
- mapTableCell(cell).content
- )}
-
- ))}
-
- ))}
-
-);
+}) => {
+ // If headerRows is 1, then the first row is a header row
+ const headerRows = new Array(props.data.headerRows ?? 0).fill(true);
+ // If headerCols is 1, then the first column is a header column
+ const headerCols = new Array(props.data.headerCols ?? 0).fill(true);
+
+ return (
+
+ {props.data.rows.map((row, rowIndex) => (
+
+ {row.cells.map((c, colIndex) => {
+ const cell = mapTableCell(c);
+
+ const isHeaderRow = headerRows[rowIndex];
+ const isHeaderCol = headerCols[colIndex];
+
+ // TODO we need to support for colspan and rowspan, but at the moment are blocked by react-pdf
+ return (
+
+ {props.transformer.transformInlineContent(cell.content)}
+
+ );
+ })}
+
+ ))}
+
+ );
+};