邮件导出
可以将 BlockNote 文档导出为兼容邮件的 HTML,且完全在客户端完成。
此功能由 @blocknote/xl-email-exporter 提供。xl- 系列包
是完全开源的,但采用了 copyleft 许可证。商业许可证
用于闭源专有产品,包含在
商业订阅 中。
首先,安装 @blocknote/xl-email-exporter 包:
npm install @blocknote/xl-email-exporter然后,创建 ReactEmailExporter 类的实例。它提供以下方法:
import {
ReactEmailExporter,
reactEmailDefaultSchemaMappings,
} from "@blocknote/xl-email-exporter";
// 创建导出器
const exporter = new ReactEmailExporter(
editor.schema,
reactEmailDefaultSchemaMappings,
);
// 将区块转换为 react-email 文档
const html = await exporter.toReactEmailDocument(editor.document);
// 使用 react-email 写入文件:
await ReactEmail.render(html, `filename.html`);请参见下面的完整示例:
自定义邮件输出
toReactEmailDocument 接受一个可选的 options 参数,允许你自定义:
- preview:设置邮件预览文本(可以是字符串或字符串数组)
- header:在邮件顶部添加内容(必须是 React-Email 兼容组件)
- footer:在邮件底部添加内容(必须是 React-Email 兼容组件)
- head:向 Head 组件 注入元素
- container:自定义容器组件(将包裹邮件内容,包括头部和底部)
- bodyStyles:自定义正文样式(一个
CSSProperties对象),提供此对象会完全覆盖默认样式
示例用法:
import React from "react";
import {
ReactEmailExporter,
reactEmailDefaultSchemaMappings,
} from "@blocknote/xl-email-exporter";
import { BlockNoteEditor } from "@blocknote/core";
import { Text, Container } from "@react-email/components";
const editor = BlockNoteEditor.create();
// ---cut---
const exporter = new ReactEmailExporter(
editor.schema,
reactEmailDefaultSchemaMappings,
);
const html = await exporter.toReactEmailDocument(editor.document, {
preview: "这是邮件内容的预览文本",
header: <Text>头部</Text>,
footer: <Text>底部</Text>,
head: <title>我的邮件</title>,
container: ({ children }) => <Container>{children}</Container>,
// 以下是默认设置的正文样式
bodyStyles: {
fontFamily:
"'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif",
fontSize: "16px",
lineHeight: "1.5",
color: "#333",
},
});自定义映射 / 自定义 Schema
ReactEmailExporter 构造函数接受 schema 和 mappings 参数。
映射定义了如何将 BlockNote 的 schema 元素(区块、内联内容或样式)转换为 React-Email 元素。
如果你在编辑器中使用了自定义 schema,或者想覆盖默认 BlockNote 元素转换为 React Email 的行为,可以传入你自己的 mappings:
例如,当你的 schema 有一个 extraBlock 类型时:
import { ReactEmailExporter, reactEmailDefaultSchemaMappings } from "@blocknote/xl-email-exporter";
import { Text } from "@react-email/components";
new ReactEmailExporter(schema, {
blockMapping: {
...reactEmailDefaultSchemaMappings.blockMapping,
myCustomBlock: (block, exporter) => {
return <Text>我的自定义区块</Text>;
},
},
inlineContentMapping: reactEmailDefaultSchemaMappings.inlineContentMapping,
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
});导出器选项
ReactEmailExporter 构造函数还接受一个可选的 options 参数。
虽然转换过程在客户端完成,默认配置使用了服务器托管的代理来解决文件解析:
const defaultOptions = {
// 一个用于解析外部资源的函数,避免 CORS 问题
// 默认为调用 BlockNote 托管的服务器端代理进行文件解析
resolveFileUrl: corsProxyResolveFileUrl,
// the strings rendered into the exported document (file link texts, error
// placeholders); pass a locale from @blocknote/core/locales (or your
// editor's dictionary) to export in another language
dictionary: locales.en,
// the colors to use in the email for things like highlighting, background colors and font colors.
colors: COLORS_DEFAULT, // defaults from @blocknote/core
};自定义样式
想调整邮件的默认样式?你可以使用 reactEmailDefaultSchemaMappingsWithStyles 来创建带有自定义样式的映射。
import {
ReactEmailExporter,
reactEmailDefaultSchemaMappingsWithStyles,
} from "@blocknote/xl-email-exporter";
import { Text } from "@react-email/components";
const { blockMapping, inlineContentMapping, styleMapping } =
reactEmailDefaultSchemaMappingsWithStyles({
textStyles: {
paragraph: {
style: {
fontSize: 16,
lineHeight: 1.5,
margin: 3,
minHeight: 24,
},
},
},
});
new ReactEmailExporter(schema, {
// 你依然可以使用默认区块映射,也可以覆盖它
blockMapping: {
...blockMapping,
audio: (block, exporter) => {
return <Text>音频区块</Text>;
},
},
inlineContentMapping,
styleMapping,
});数学和图表区块
数学和图表区块自带邮件映射,会将其导出为图像,并将 LaTeX/Mermaid 源代码作为 alt 文本。有关设置,请参见导出数学内容和导出图表。
图像传递。 默认情况下,图像会嵌入为数据 URL,这种方式自包含,但某些邮件客户端(尤其是 Gmail 和 Windows 版 Outlook)不会显示数据 URL 图像,而是显示 alt 文本。对于这些客户端,请将图像作为内联 cid: 附件传递(这是嵌入生成图像时支持最广泛的方式),并在发送时将收集到的附件传递给邮件发送器:
import {
ReactEmailExporter,
reactEmailDefaultSchemaMappings,
createCIDImageDelivery,
} from "@blocknote/xl-email-exporter";
import {
createInlineMathMapping,
createMathBlockMapping,
} from "@blocknote/math-block/email-exporter";
import { createDiagramBlockMapping } from "@blocknote/diagram-block/email-exporter";
const imageDelivery = createCIDImageDelivery();
const exporter = new ReactEmailExporter(editor.schema, {
...reactEmailDefaultSchemaMappings,
blockMapping: {
...reactEmailDefaultSchemaMappings.blockMapping,
mathBlock: createMathBlockMapping({ imageDelivery }),
diagram: createDiagramBlockMapping({ imageDelivery }),
},
inlineContentMapping: {
...reactEmailDefaultSchemaMappings.inlineContentMapping,
math: createInlineMathMapping({ imageDelivery }),
},
});
const html = await exporter.toReactEmailDocument(editor.document);
// e.g. with nodemailer (works the same with other mailers):
await transporter.sendMail({ html, attachments: imageDelivery.attachments });