Skip to content

Commit 9a8f957

Browse files
feat: Code block support in PDF & DOCX exporters (#1367)
* feat: Support for code blocks in PDF exporter * feat: Support for code blocks in DOCX exporter * fix: Use Geist Mono for inline code tags in DOCX export * fix: Background color, example formatting, style definition * Removed TODO --------- Co-authored-by: matthewlipski <[email protected]>
1 parent c0bc5d0 commit 9a8f957

File tree

15 files changed

+170
-44
lines changed

15 files changed

+170
-44
lines changed

examples/05-interoperability/05-converting-blocks-to-pdf/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,15 @@ export default function App() {
282282
],
283283
},
284284
},
285+
{
286+
type: "codeBlock",
287+
props: {
288+
language: "javascript",
289+
},
290+
content: `const helloWorld = (message) => {
291+
console.log("Hello World", message);
292+
};`,
293+
},
285294
],
286295
});
287296

examples/05-interoperability/06-converting-blocks-to-docx/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,15 @@ export default function App() {
277277
],
278278
},
279279
},
280+
{
281+
type: "codeBlock",
282+
props: {
283+
language: "javascript",
284+
},
285+
content: `const helloWorld = (message) => {
286+
console.log("Hello World", message);
287+
};`,
288+
},
280289
],
281290
});
282291

packages/xl-docx-exporter/src/docx/__snapshots__/basic/document.xml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,6 @@
112112
<w:t xml:space="preserve">justified paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</w:t>
113113
</w:r>
114114
</w:p>
115-
<w:p>
116-
<w:pPr>
117-
<w:pStyle w:val="Codeblock"/>
118-
</w:pPr>
119-
<w:r>
120-
<w:t xml:space="preserve">Code Block
121-
Line 2</w:t>
122-
</w:r>
123-
</w:p>
124115
<w:p>
125116
<w:pPr>
126117
<w:pStyle w:val="ListParagraph"/>
@@ -675,6 +666,23 @@ Line 2</w:t>
675666
</w:tc>
676667
</w:tr>
677668
</w:tbl>
669+
<w:p>
670+
<w:pPr>
671+
<w:pStyle w:val="Codeblock"/>
672+
<w:shd w:fill="161616" w:color="161616" w:val="solid"/>
673+
</w:pPr>
674+
<w:r>
675+
<w:t xml:space="preserve">const helloWorld = (message) =&gt; {</w:t>
676+
</w:r>
677+
<w:r>
678+
<w:br/>
679+
<w:t xml:space="preserve"> console.log(&quot;Hello World&quot;, message);</w:t>
680+
</w:r>
681+
<w:r>
682+
<w:br/>
683+
<w:t xml:space="preserve">};</w:t>
684+
</w:r>
685+
</w:p>
678686
<w:sectPr>
679687
<w:pgSz w:w="11906" w:h="16838" w:orient="portrait"/>
680688
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>

packages/xl-docx-exporter/src/docx/__snapshots__/basic/styles.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,8 +953,8 @@
953953
<w:basedOn w:val="Normal"/>
954954
<w:rPr>
955955
<w:noProof/>
956-
<w:color w:val="e1e4e8"/>
957-
<w:shd w:fill="161616"/>
956+
<w:color w:val="ffffff"/>
957+
<w:rFonts w:ascii="GeistMono" w:cs="GeistMono" w:eastAsia="GeistMono" w:hAnsi="GeistMono"/>
958958
</w:rPr>
959959
</w:style>
960960
</w:styles>

packages/xl-docx-exporter/src/docx/defaultSchema/blocks.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
COLORS_DEFAULT,
44
DefaultBlockSchema,
55
DefaultProps,
6+
StyledText,
67
UnreachableCaseError,
78
} from "@blocknote/core";
89
import {
@@ -131,17 +132,24 @@ export const docxBlockMappingForDefaultSchema: BlockMapping<
131132
...caption(block.props, exporter),
132133
];
133134
},
134-
// TODO
135-
codeBlock: (block, exporter) => {
135+
codeBlock: (block) => {
136+
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
137+
136138
return new Paragraph({
137-
// ...blockPropsToStyles(block.props, exporter.options.colors),
138139
style: "Codeblock",
139-
children: exporter.transformInlineContent(block.content),
140-
// children: [
141-
// new TextRun({
142-
// text: block..type + " not implemented",
143-
// }),
144-
// ],
140+
shading: {
141+
type: ShadingType.SOLID,
142+
fill: "161616",
143+
color: "161616",
144+
},
145+
children: [
146+
...textContent.split("\n").map((line, index) => {
147+
return new TextRun({
148+
text: line,
149+
break: index > 0 ? 1 : 0,
150+
});
151+
}),
152+
],
145153
});
146154
},
147155
image: async (block, exporter) => {

packages/xl-docx-exporter/src/docx/defaultSchema/styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const docxStyleMappingForDefaultSchema: StyleMapping<
6767
return {};
6868
}
6969
return {
70-
font: "Courier New",
70+
font: "GeistMono",
7171
};
7272
},
7373
};

packages/xl-docx-exporter/src/docx/docxExporter.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,35 @@ export class DOCXExporter<
142142
// Unfortunately, loading the variable font doesn't work
143143
// "./src/fonts/Inter-VariableFont_opsz,wght.ttf",
144144

145-
let font = await loadFileBuffer(
145+
let interFont = await loadFileBuffer(
146146
await import("@shared/assets/fonts/inter/Inter_18pt-Regular.ttf")
147147
);
148+
let geistMonoFont = await loadFileBuffer(
149+
await import("@shared/assets/fonts/GeistMono-Regular.ttf")
150+
);
148151

149-
if (font instanceof ArrayBuffer) {
150-
// conversionw with Polyfill needed because docxjs requires Buffer
152+
if (
153+
interFont instanceof ArrayBuffer ||
154+
geistMonoFont instanceof Uint8Array
155+
) {
156+
// conversion with Polyfill needed because docxjs requires Buffer
151157
const Buffer = (await import("buffer")).Buffer;
152-
font = Buffer.from(font);
158+
159+
if (interFont instanceof ArrayBuffer) {
160+
interFont = Buffer.from(interFont);
161+
}
162+
if (geistMonoFont instanceof ArrayBuffer) {
163+
geistMonoFont = Buffer.from(geistMonoFont);
164+
}
153165
}
154166

155-
return [{ name: "Inter", data: font as Buffer }];
167+
return [
168+
{ name: "Inter", data: interFont as Buffer },
169+
{
170+
name: "GeistMono",
171+
data: geistMonoFont as Buffer,
172+
},
173+
];
156174
}
157175

158176
protected async createDefaultDocumentOptions(): Promise<DocumentOptions> {

packages/xl-docx-exporter/src/docx/template/word/styles.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,8 +983,8 @@
983983
<w:basedOn w:val="Normal" />
984984
<w:rPr>
985985
<w:noProof />
986-
<w:color w:val="e1e4e8" />
987-
<w:shd w:fill="161616" />
986+
<w:color w:val="ffffff"/>
987+
<w:rFonts w:ascii="GeistMono" w:cs="GeistMono" w:eastAsia="GeistMono" w:hAnsi="GeistMono"/>
988988
</w:rPr>
989989
</w:style>
990990
</w:styles>

packages/xl-pdf-exporter/src/pdf/__snapshots__/example.jsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,6 @@
9898
</text>
9999
</text>
100100
</view>
101-
<view>
102-
<text>
103-
codeBlock not implemented
104-
</text>
105-
</view>
106101
<view
107102
style="text-align: left;"
108103
>
@@ -586,6 +581,27 @@
586581
</view>
587582
</view>
588583
</view>
584+
<view>
585+
<view
586+
style="padding: 18px; background-color: rgb(22, 22, 22); color: rgb(255, 255, 255); line-height: 1.25; font-size: 12px; font-family: GeistMono;"
587+
>
588+
<text
589+
style="margin-left: 0px;"
590+
>
591+
const helloWorld = (message) =&gt; {
592+
</text>
593+
<text
594+
style="margin-left: 14.25px;"
595+
>
596+
console.log("Hello World", message);
597+
</text>
598+
<text
599+
style="margin-left: 0px;"
600+
>
601+
};
602+
</text>
603+
</view>
604+
</view>
589605
</view>
590606
</page>
591607
</document>

packages/xl-pdf-exporter/src/pdf/__snapshots__/exampleWithHeaderAndFooter.jsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@
103103
</text>
104104
</text>
105105
</view>
106-
<view>
107-
<text>
108-
codeBlock not implemented
109-
</text>
110-
</view>
111106
<view
112107
style="text-align: left;"
113108
>
@@ -591,6 +586,27 @@
591586
</view>
592587
</view>
593588
</view>
589+
<view>
590+
<view
591+
style="padding: 18px; background-color: rgb(22, 22, 22); color: rgb(255, 255, 255); line-height: 1.25; font-size: 12px; font-family: GeistMono;"
592+
>
593+
<text
594+
style="margin-left: 0px;"
595+
>
596+
const helloWorld = (message) =&gt; {
597+
</text>
598+
<text
599+
style="margin-left: 14.25px;"
600+
>
601+
console.log("Hello World", message);
602+
</text>
603+
<text
604+
style="margin-left: 0px;"
605+
>
606+
};
607+
</text>
608+
</view>
609+
</view>
594610
</view>
595611
<view>
596612
<text>

0 commit comments

Comments
 (0)