Skip to content

Commit 8f496a0

Browse files
jmarbuttnperez0111
andauthored
feat(xl-email-exporter): add email exporter (#1768)
Co-authored-by: Nick the Sick <[email protected]>
1 parent 7a21426 commit 8f496a0

33 files changed

+2947
-5
lines changed

docs/pages/docs/editor-api/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"export-to-pdf": "",
88
"export-to-docx": "",
99
"export-to-odt": "",
10+
"export-to-email": "",
1011
"events": "",
1112
"methods": ""
1213
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
title: Export to email
3+
description: Export BlockNote documents to an email.
4+
imageTitle: Export to email
5+
path: /docs/export-to-email
6+
---
7+
8+
import { Example } from "@/components/example";
9+
import { Callout } from "nextra/components";
10+
11+
# Exporting blocks to email
12+
13+
Leveraging the [React Email](https://react.email/) library, it's possible to export BlockNote documents to email, completely client-side.
14+
15+
<Callout type={"info"}>
16+
This feature is provided by the `@blocknote/xl-email-exporter`. `xl-` packages
17+
are fully open source, but released under a copyleft license. A commercial
18+
license for usage in closed source, proprietary products comes as part of the
19+
[Business subscription](/pricing).
20+
</Callout>
21+
22+
First, install the `@blocknote/xl-email-exporter` packages:
23+
24+
```bash
25+
npm install @blocknote/xl-email-exporter
26+
```
27+
28+
Then, create an instance of the `ReactEmailExporter` class. This exposes the following methods:
29+
30+
```typescript
31+
import {
32+
ReactEmailExporter,
33+
reactEmailDefaultSchemaMappings,
34+
} from "@blocknote/xl-email-exporter";
35+
36+
// Create the exporter
37+
const exporter = new ReactEmailExporter(editor.schema, reactEmailDefaultSchemaMappings);
38+
39+
// Convert the blocks to a react-email document
40+
const html = await exporter.toReactEmailDocument(editor.document);
41+
42+
// Use react-email to write to file:
43+
await ReactEmail.render(html, `filename.html`);
44+
```
45+
46+
See the [full example](/examples/interoperability/converting-blocks-to-react-email) with live React Email preview below:
47+
48+
<Example name="interoperability/converting-blocks-to-react-email" />
49+
50+
### Customizing the Email
51+
52+
`toReactEmailDocument` takes an optional `options` parameter, which allows you to customize:
53+
54+
- **preview**: Set the preview text for the email (can be a string or an array of strings)
55+
- **header**: Add content to the top of the email (must be a React-Email compatible component)
56+
- **footer**: Add content to the bottom of the email (must be a React-Email compatible component)
57+
- **head**: Inject elements into the [Head element](https://react.email/docs/components/head)
58+
59+
Example usage:
60+
61+
```tsx
62+
import { Text } from "@react-email/components";
63+
const html = await exporter.toReactEmailDocument(editor.document, {
64+
preview: "This is a preview of the email content",
65+
header: <Text>Header</Text>,
66+
footer: <Text>Footer</Text>,
67+
head: <title>My email</title>,
68+
});
69+
```
70+
71+
### Custom mappings / custom schemas
72+
73+
The `ReactEmailExporter` constructor takes a `schema` and `mappings` parameter.
74+
A _mapping_ defines how to convert a BlockNote schema element (a Block, Inline Content, or Style) to a React-Email element.
75+
If you're using a [custom schema](/docs/custom-schemas) in your editor, or if you want to overwrite how default BlockNote elements are converted to React Email, you can pass your own `mappings`:
76+
77+
For example, use the following code in case your schema has an `extraBlock` type:
78+
79+
```typescript
80+
import { ReactEmailExporter, reactEmailDefaultSchemaMappings } from "@blocknote/xl-email-exporter";
81+
import { Text } from "@react-email/components";
82+
83+
new ReactEmailExporter(schema, {
84+
blockMapping: {
85+
...reactEmailDefaultSchemaMappings.blockMapping,
86+
myCustomBlock: (block, exporter) => {
87+
return <Text>My custom block</Text>;
88+
},
89+
},
90+
inlineContentMapping: reactEmailDefaultSchemaMappings.inlineContentMapping,
91+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
92+
});
93+
```
94+
95+
### Exporter options
96+
97+
The `ReactEmailExporter` constructor takes an optional `options` parameter.
98+
While conversion happens on the client-side, the default setup uses two server based resources:
99+
100+
```typescript
101+
const defaultOptions = {
102+
// a function to resolve external resources in order to avoid CORS issues
103+
// by default, this calls a BlockNote hosted server-side proxy to resolve files
104+
resolveFileUrl: corsProxyResolveFileUrl,
105+
// the colors to use in the email
106+
colors: COLORS_DEFAULT, // defaults from @blocknote/core
107+
};
108+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"playground": true,
3+
"docs": true,
4+
"author": "jmarbutt",
5+
"tags": [""],
6+
"dependencies": {
7+
"@blocknote/xl-email-exporter": "latest",
8+
"@react-email/render": "^1.1.2"
9+
},
10+
"pro": true
11+
}

0 commit comments

Comments
 (0)