Skip to content

Commit e560634

Browse files
committed
Added exporters
1 parent f5ba0b1 commit e560634

4 files changed

Lines changed: 149 additions & 98 deletions

File tree

  • packages
    • xl-docx-exporter/src/docx/defaultSchema
    • xl-email-exporter/src/react-email/defaultSchema
    • xl-odt-exporter/src/odt/defaultSchema
    • xl-pdf-exporter/src/pdf/defaultSchema

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

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {
2+
BlockConfig,
3+
BlockFromConfigNoChildren,
24
BlockMapping,
35
COLORS_DEFAULT,
46
createPageBreakBlockConfig,
@@ -25,6 +27,11 @@ import {
2527
import { Table } from "../util/Table.js";
2628
import { multiColumnSchema } from "@blocknote/xl-multi-column";
2729

30+
type BSchema = DefaultBlockSchema & {
31+
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
32+
math: BlockConfig<"math", {}, "inline">;
33+
} & typeof multiColumnSchema.blockSchema;
34+
2835
function blockPropsToStyles(
2936
props: Partial<DefaultProps>,
3037
colors: typeof COLORS_DEFAULT,
@@ -69,10 +76,27 @@ function blockPropsToStyles(
6976
})(),
7077
};
7178
}
79+
80+
const codeMapping = (
81+
block: BlockFromConfigNoChildren<BSchema[keyof BSchema], any, any>,
82+
) => {
83+
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
84+
85+
return new Paragraph({
86+
style: "SourceCode",
87+
children: [
88+
...textContent.split("\n").map((line, index) => {
89+
return new TextRun({
90+
text: line,
91+
break: index > 0 ? 1 : 0,
92+
});
93+
}),
94+
],
95+
});
96+
};
97+
7298
export const docxBlockMappingForDefaultSchema: BlockMapping<
73-
DefaultBlockSchema & {
74-
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
75-
} & typeof multiColumnSchema.blockSchema,
99+
BSchema,
76100
any,
77101
any,
78102
| Promise<Paragraph[] | Paragraph | DocxTable>
@@ -162,21 +186,8 @@ export const docxBlockMappingForDefaultSchema: BlockMapping<
162186
...caption(block.props, exporter),
163187
];
164188
},
165-
codeBlock: (block) => {
166-
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
167-
168-
return new Paragraph({
169-
style: "SourceCode",
170-
children: [
171-
...textContent.split("\n").map((line, index) => {
172-
return new TextRun({
173-
text: line,
174-
break: index > 0 ? 1 : 0,
175-
});
176-
}),
177-
],
178-
});
179-
},
189+
codeBlock: codeMapping,
190+
math: codeMapping,
180191
pageBreak: () => {
181192
return new Paragraph({
182193
children: [new PageBreak()],

packages/xl-email-exporter/src/react-email/defaultSchema/blocks.tsx

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {
2+
BlockConfig,
3+
BlockFromConfigNoChildren,
24
BlockMapping,
35
createPageBreakBlockConfig,
46
DefaultBlockSchema,
@@ -115,12 +117,40 @@ export const defaultReactEmailTextStyles = {
115117
},
116118
} satisfies ReactEmailTextStyles;
117119

120+
type BSchema = DefaultBlockSchema & {
121+
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
122+
math: BlockConfig<"math", {}, "inline">;
123+
};
124+
125+
// Renders a block's inline content as a code block. Used for both code blocks
126+
// and math blocks (which store their LaTeX source as content); math has no
127+
// language, so it's passed explicitly.
128+
const codeMapping = (
129+
block: BlockFromConfigNoChildren<BSchema[keyof BSchema], any, any>,
130+
language: PrismLanguage,
131+
textStyles: ReactEmailTextStyles,
132+
) => {
133+
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
134+
135+
return (
136+
<CodeBlock
137+
code={textContent}
138+
fontFamily="'CommitMono', monospace"
139+
language={language}
140+
theme={dracula}
141+
{...textStyles.codeBlock}
142+
style={{
143+
...defaultReactEmailTextStyles.codeBlock.style,
144+
...textStyles.codeBlock?.style,
145+
}}
146+
/>
147+
);
148+
};
149+
118150
export const createReactEmailBlockMappingForDefaultSchema = (
119151
textStyles: ReactEmailTextStyles = defaultReactEmailTextStyles,
120152
): BlockMapping<
121-
DefaultBlockSchema & {
122-
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
123-
},
153+
BSchema,
124154
any,
125155
any,
126156
React.ReactElement<any>,
@@ -259,23 +289,9 @@ export const createReactEmailBlockMappingForDefaultSchema = (
259289
);
260290
},
261291

262-
codeBlock: (block) => {
263-
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
264-
265-
return (
266-
<CodeBlock
267-
code={textContent}
268-
fontFamily="'CommitMono', monospace"
269-
language={block.props.language as PrismLanguage}
270-
theme={dracula}
271-
{...textStyles.codeBlock}
272-
style={{
273-
...defaultReactEmailTextStyles.codeBlock.style,
274-
...textStyles.codeBlock?.style,
275-
}}
276-
/>
277-
);
278-
},
292+
codeBlock: (block) =>
293+
codeMapping(block, block.props.language as PrismLanguage, textStyles),
294+
math: (block) => codeMapping(block, "latex" as PrismLanguage, textStyles),
279295
audio: (block) => {
280296
// Audio icon SVG
281297
const icon = (

packages/xl-odt-exporter/src/odt/defaultSchema/blocks.tsx

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {
2+
BlockConfig,
23
BlockFromConfig,
4+
BlockFromConfigNoChildren,
35
BlockMapping,
46
createPageBreakBlockConfig,
57
DefaultBlockSchema,
@@ -11,6 +13,32 @@ import {
1113
import { ODTExporter } from "../odtExporter.js";
1214
import { multiColumnSchema } from "@blocknote/xl-multi-column";
1315

16+
type BSchema = DefaultBlockSchema & {
17+
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
18+
math: BlockConfig<"math", {}, "inline">;
19+
} & typeof multiColumnSchema.blockSchema;
20+
21+
// Renders a block's inline content as a code paragraph. Used for both code
22+
// blocks and math blocks (which store their LaTeX source as content).
23+
const codeMapping = (
24+
block: BlockFromConfigNoChildren<BSchema[keyof BSchema], any, any>,
25+
) => {
26+
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
27+
28+
return (
29+
<text:p text:style-name="Codeblock">
30+
{...textContent.split("\n").map((line, index) => {
31+
return (
32+
<>
33+
{index !== 0 && <text:line-break />}
34+
{line}
35+
</>
36+
);
37+
})}
38+
</text:p>
39+
);
40+
};
41+
1442
export const getTabs = (nestingLevel: number) => {
1543
return Array.from({ length: nestingLevel }, (_, i) => <text:tab key={i} />);
1644
};
@@ -164,9 +192,7 @@ const wrapWithLists = (
164192
};
165193

166194
export const odtBlockMappingForDefaultSchema: BlockMapping<
167-
DefaultBlockSchema & {
168-
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
169-
} & typeof multiColumnSchema.blockSchema,
195+
BSchema,
170196
any,
171197
any,
172198
React.ReactNode,
@@ -500,22 +526,8 @@ export const odtBlockMappingForDefaultSchema: BlockMapping<
500526
);
501527
},
502528

503-
codeBlock: (block) => {
504-
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
505-
506-
return (
507-
<text:p text:style-name="Codeblock">
508-
{...textContent.split("\n").map((line, index) => {
509-
return (
510-
<>
511-
{index !== 0 && <text:line-break />}
512-
{line}
513-
</>
514-
);
515-
})}
516-
</text:p>
517-
);
518-
},
529+
codeBlock: codeMapping,
530+
math: codeMapping,
519531

520532
file: async (block) => {
521533
return (

packages/xl-pdf-exporter/src/pdf/defaultSchema/blocks.tsx

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {
2+
BlockConfig,
3+
BlockFromConfigNoChildren,
24
BlockMapping,
35
DefaultBlockSchema,
46
DefaultProps,
@@ -19,10 +21,56 @@ import { Table } from "../util/table/Table.js";
1921
const PIXELS_PER_POINT = 0.75;
2022
const FONT_SIZE = 16;
2123

24+
type BSchema = DefaultBlockSchema & {
25+
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
26+
math: BlockConfig<"math", {}, "inline">;
27+
} & typeof multiColumnSchema.blockSchema;
28+
29+
// Renders a block's inline content as monospaced source code. Used for both
30+
// code blocks and math blocks (which store their LaTeX source as content).
31+
const codeMapping = (
32+
block: BlockFromConfigNoChildren<BSchema[keyof BSchema], any, any>,
33+
) => {
34+
// Code blocks should always contain a single `StyledText` inline content.
35+
// However, if this is not the case for whatever reason, we can merge the
36+
// text content of all `StyledText` content in them.
37+
const textContent = (block.content as StyledText<any>[])
38+
.map((item) => item.text)
39+
.join("");
40+
const lines = textContent.split("\n").map((line, index) => {
41+
const indent = line.match(/^\s*/)?.[0].length || 0;
42+
43+
return (
44+
<Text
45+
key={`line_${index}` + block.id}
46+
style={{
47+
marginLeft: indent * 9.5 * PIXELS_PER_POINT,
48+
}}
49+
>
50+
{line.trimStart() || <>&nbsp;</>}
51+
</Text>
52+
);
53+
});
54+
55+
return (
56+
<View
57+
wrap={false}
58+
style={{
59+
padding: 24 * PIXELS_PER_POINT,
60+
border: "1px solid #000000",
61+
lineHeight: 1.25,
62+
fontSize: FONT_SIZE * PIXELS_PER_POINT,
63+
fontFamily: "GeistMono",
64+
}}
65+
key={"codeBlock" + block.id}
66+
>
67+
{lines}
68+
</View>
69+
);
70+
};
71+
2272
export const pdfBlockMappingForDefaultSchema: BlockMapping<
23-
DefaultBlockSchema & {
24-
pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
25-
} & typeof multiColumnSchema.blockSchema,
73+
BSchema,
2674
any,
2775
any,
2876
React.ReactElement<Text>,
@@ -113,44 +161,8 @@ export const pdfBlockMappingForDefaultSchema: BlockMapping<
113161
</Text>
114162
);
115163
},
116-
codeBlock: (block) => {
117-
// Code blocks should always contain a single `StyledText` inline content.
118-
// However, if this is not the case for whatever reason, we can merge the
119-
// text content of all `StyledText` content in them.
120-
const textContent = (block.content as StyledText<any>[])
121-
.map((item) => item.text)
122-
.join("");
123-
const lines = textContent.split("\n").map((line, index) => {
124-
const indent = line.match(/^\s*/)?.[0].length || 0;
125-
126-
return (
127-
<Text
128-
key={`line_${index}` + block.id}
129-
style={{
130-
marginLeft: indent * 9.5 * PIXELS_PER_POINT,
131-
}}
132-
>
133-
{line.trimStart() || <>&nbsp;</>}
134-
</Text>
135-
);
136-
});
137-
138-
return (
139-
<View
140-
wrap={false}
141-
style={{
142-
padding: 24 * PIXELS_PER_POINT,
143-
border: "1px solid #000000",
144-
lineHeight: 1.25,
145-
fontSize: FONT_SIZE * PIXELS_PER_POINT,
146-
fontFamily: "GeistMono",
147-
}}
148-
key={"codeBlock" + block.id}
149-
>
150-
{lines}
151-
</View>
152-
);
153-
},
164+
codeBlock: codeMapping,
165+
math: codeMapping,
154166
pageBreak: () => {
155167
return <View break key={"pageBreak"} />;
156168
},

0 commit comments

Comments
 (0)