@blocknote/xl-email-exporter 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/dist/blocknote-xl-email-exporter.js +1097 -0
- package/dist/blocknote-xl-email-exporter.js.map +1 -0
- package/dist/blocknote-xl-email-exporter.umd.cjs +31 -0
- package/dist/blocknote-xl-email-exporter.umd.cjs.map +1 -0
- package/dist/webpack-stats.json +1 -0
- package/package.json +87 -0
- package/src/index.ts +1 -0
- package/src/react-email/__snapshots__/reactEmailExporter.test.tsx.snap +35 -0
- package/src/react-email/defaultSchema/blocks.tsx +350 -0
- package/src/react-email/defaultSchema/index.ts +9 -0
- package/src/react-email/defaultSchema/inlinecontent.tsx +26 -0
- package/src/react-email/defaultSchema/styles.tsx +61 -0
- package/src/react-email/index.ts +2 -0
- package/src/react-email/reactEmailExporter.test.tsx +780 -0
- package/src/react-email/reactEmailExporter.tsx +334 -0
- package/src/vite-env.d.ts +11 -0
- package/types/src/index.d.ts +1 -0
- package/types/src/react-email/defaultSchema/blocks.d.ts +4 -0
- package/types/src/react-email/defaultSchema/index.d.ts +654 -0
- package/types/src/react-email/defaultSchema/inlinecontent.d.ts +4 -0
- package/types/src/react-email/defaultSchema/styles.d.ts +3 -0
- package/types/src/react-email/index.d.ts +2 -0
- package/types/src/react-email/reactEmailExporter.d.ts +36 -0
- package/types/src/react-email/reactEmailExporter.test.d.ts +1 -0
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { ReactEmailExporter } from "./reactEmailExporter.jsx";
|
|
3
|
+
import { reactEmailDefaultSchemaMappings } from "./defaultSchema/index.js";
|
|
4
|
+
import {
|
|
5
|
+
BlockNoteSchema,
|
|
6
|
+
createBlockSpec,
|
|
7
|
+
createInlineContentSpec,
|
|
8
|
+
createStyleSpec,
|
|
9
|
+
defaultBlockSpecs,
|
|
10
|
+
defaultInlineContentSpecs,
|
|
11
|
+
defaultStyleSpecs,
|
|
12
|
+
PageBreak,
|
|
13
|
+
} from "@blocknote/core";
|
|
14
|
+
import { testDocument } from "@shared/testDocument.js";
|
|
15
|
+
|
|
16
|
+
describe("react email exporter", () => {
|
|
17
|
+
it("should export a document (HTML snapshot)", async () => {
|
|
18
|
+
const exporter = new ReactEmailExporter(
|
|
19
|
+
BlockNoteSchema.create(),
|
|
20
|
+
reactEmailDefaultSchemaMappings,
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const html = await exporter.toReactEmailDocument(testDocument as any);
|
|
24
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporter");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("typescript: schema with extra block", async () => {
|
|
28
|
+
const schema = BlockNoteSchema.create({
|
|
29
|
+
blockSpecs: {
|
|
30
|
+
...defaultBlockSpecs,
|
|
31
|
+
pageBreak: PageBreak,
|
|
32
|
+
extraBlock: createBlockSpec(
|
|
33
|
+
{
|
|
34
|
+
content: "none",
|
|
35
|
+
type: "extraBlock",
|
|
36
|
+
propSchema: {},
|
|
37
|
+
},
|
|
38
|
+
{} as any,
|
|
39
|
+
),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
new ReactEmailExporter(
|
|
44
|
+
schema,
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
reactEmailDefaultSchemaMappings,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
new ReactEmailExporter(schema, {
|
|
50
|
+
// @ts-expect-error
|
|
51
|
+
blockMapping: reactEmailDefaultSchemaMappings.blockMapping,
|
|
52
|
+
inlineContentMapping:
|
|
53
|
+
reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
54
|
+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
new ReactEmailExporter(schema, {
|
|
58
|
+
blockMapping: {
|
|
59
|
+
...reactEmailDefaultSchemaMappings.blockMapping,
|
|
60
|
+
extraBlock: (_b, _t) => {
|
|
61
|
+
throw new Error("extraBlock not implemented");
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
inlineContentMapping:
|
|
65
|
+
reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
66
|
+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("typescript: schema with extra inline content", async () => {
|
|
71
|
+
const schema = BlockNoteSchema.create({
|
|
72
|
+
inlineContentSpecs: {
|
|
73
|
+
...defaultInlineContentSpecs,
|
|
74
|
+
extraInlineContent: createInlineContentSpec(
|
|
75
|
+
{
|
|
76
|
+
type: "extraInlineContent",
|
|
77
|
+
content: "styled",
|
|
78
|
+
propSchema: {},
|
|
79
|
+
},
|
|
80
|
+
{} as any,
|
|
81
|
+
),
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
new ReactEmailExporter(
|
|
86
|
+
schema,
|
|
87
|
+
// @ts-expect-error
|
|
88
|
+
reactEmailDefaultSchemaMappings,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
new ReactEmailExporter(schema, {
|
|
92
|
+
blockMapping: reactEmailDefaultSchemaMappings.blockMapping,
|
|
93
|
+
// @ts-expect-error
|
|
94
|
+
inlineContentMapping:
|
|
95
|
+
reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
96
|
+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// no error
|
|
100
|
+
new ReactEmailExporter(schema, {
|
|
101
|
+
blockMapping: reactEmailDefaultSchemaMappings.blockMapping,
|
|
102
|
+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
|
|
103
|
+
inlineContentMapping: {
|
|
104
|
+
...reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
105
|
+
extraInlineContent: () => {
|
|
106
|
+
throw new Error("extraInlineContent not implemented");
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("typescript: schema with extra style", async () => {
|
|
113
|
+
const schema = BlockNoteSchema.create({
|
|
114
|
+
styleSpecs: {
|
|
115
|
+
...defaultStyleSpecs,
|
|
116
|
+
extraStyle: createStyleSpec(
|
|
117
|
+
{
|
|
118
|
+
type: "extraStyle",
|
|
119
|
+
propSchema: "boolean",
|
|
120
|
+
},
|
|
121
|
+
{} as any,
|
|
122
|
+
),
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
new ReactEmailExporter(
|
|
127
|
+
schema,
|
|
128
|
+
// @ts-expect-error
|
|
129
|
+
reactEmailDefaultSchemaMappings,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
new ReactEmailExporter(schema, {
|
|
133
|
+
blockMapping: reactEmailDefaultSchemaMappings.blockMapping,
|
|
134
|
+
inlineContentMapping:
|
|
135
|
+
reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
136
|
+
// @ts-expect-error
|
|
137
|
+
styleMapping: reactEmailDefaultSchemaMappings.styleMapping,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// no error
|
|
141
|
+
new ReactEmailExporter(schema, {
|
|
142
|
+
blockMapping: reactEmailDefaultSchemaMappings.blockMapping,
|
|
143
|
+
inlineContentMapping:
|
|
144
|
+
reactEmailDefaultSchemaMappings.inlineContentMapping,
|
|
145
|
+
styleMapping: {
|
|
146
|
+
...reactEmailDefaultSchemaMappings.styleMapping,
|
|
147
|
+
extraStyle: () => {
|
|
148
|
+
throw new Error("extraStyle not implemented");
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("should export a document with preview", async () => {
|
|
155
|
+
const exporter = new ReactEmailExporter(
|
|
156
|
+
BlockNoteSchema.create({
|
|
157
|
+
blockSpecs: { ...defaultBlockSpecs, pageBreak: PageBreak },
|
|
158
|
+
}),
|
|
159
|
+
reactEmailDefaultSchemaMappings,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const html = await exporter.toReactEmailDocument(testDocument as any, {
|
|
163
|
+
preview: "This is a preview of the email content",
|
|
164
|
+
});
|
|
165
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterWithPreview");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("should export a document with multiple preview lines", async () => {
|
|
169
|
+
const exporter = new ReactEmailExporter(
|
|
170
|
+
BlockNoteSchema.create({
|
|
171
|
+
blockSpecs: { ...defaultBlockSpecs, pageBreak: PageBreak },
|
|
172
|
+
}),
|
|
173
|
+
reactEmailDefaultSchemaMappings,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const html = await exporter.toReactEmailDocument(testDocument as any, {
|
|
177
|
+
preview: ["First preview line", "Second preview line"],
|
|
178
|
+
});
|
|
179
|
+
expect(html).toMatchSnapshot(
|
|
180
|
+
"__snapshots__/reactEmailExporterWithMultiplePreview",
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should handle empty document", async () => {
|
|
185
|
+
const exporter = new ReactEmailExporter(
|
|
186
|
+
BlockNoteSchema.create(),
|
|
187
|
+
reactEmailDefaultSchemaMappings,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const html = await exporter.toReactEmailDocument([]);
|
|
191
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterEmpty");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("should handle document with only text blocks", async () => {
|
|
195
|
+
const exporter = new ReactEmailExporter(
|
|
196
|
+
BlockNoteSchema.create(),
|
|
197
|
+
reactEmailDefaultSchemaMappings,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const simpleDocument = [
|
|
201
|
+
{
|
|
202
|
+
id: "1",
|
|
203
|
+
type: "paragraph",
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: "Simple text content",
|
|
208
|
+
styles: {},
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
children: [],
|
|
212
|
+
props: {},
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
const html = await exporter.toReactEmailDocument(simpleDocument as any);
|
|
217
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterSimpleText");
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("should handle document with styled text", async () => {
|
|
221
|
+
const exporter = new ReactEmailExporter(
|
|
222
|
+
BlockNoteSchema.create(),
|
|
223
|
+
reactEmailDefaultSchemaMappings,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const styledDocument = [
|
|
227
|
+
{
|
|
228
|
+
id: "1",
|
|
229
|
+
type: "paragraph",
|
|
230
|
+
content: [
|
|
231
|
+
{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: "Bold and italic text",
|
|
234
|
+
styles: {
|
|
235
|
+
bold: true,
|
|
236
|
+
italic: true,
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
children: [],
|
|
241
|
+
props: {},
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
const html = await exporter.toReactEmailDocument(styledDocument as any);
|
|
246
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterStyledText");
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("should handle document with links", async () => {
|
|
250
|
+
const exporter = new ReactEmailExporter(
|
|
251
|
+
BlockNoteSchema.create(),
|
|
252
|
+
reactEmailDefaultSchemaMappings,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const linkDocument = [
|
|
256
|
+
{
|
|
257
|
+
id: "1",
|
|
258
|
+
type: "paragraph",
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: "link",
|
|
262
|
+
href: "https://example.com",
|
|
263
|
+
content: [
|
|
264
|
+
{
|
|
265
|
+
type: "text",
|
|
266
|
+
text: "Click here",
|
|
267
|
+
styles: {},
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
children: [],
|
|
273
|
+
props: {},
|
|
274
|
+
},
|
|
275
|
+
];
|
|
276
|
+
|
|
277
|
+
const html = await exporter.toReactEmailDocument(linkDocument as any);
|
|
278
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterWithLinks");
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("should handle document with nested lists", async () => {
|
|
282
|
+
const exporter = new ReactEmailExporter(
|
|
283
|
+
BlockNoteSchema.create(),
|
|
284
|
+
reactEmailDefaultSchemaMappings,
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const nestedListDocument = [
|
|
288
|
+
{
|
|
289
|
+
id: "1",
|
|
290
|
+
type: "bulletListItem",
|
|
291
|
+
content: [
|
|
292
|
+
{
|
|
293
|
+
type: "text",
|
|
294
|
+
text: "Parent item",
|
|
295
|
+
styles: {},
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
children: [
|
|
299
|
+
{
|
|
300
|
+
id: "2",
|
|
301
|
+
type: "bulletListItem",
|
|
302
|
+
content: [
|
|
303
|
+
{
|
|
304
|
+
type: "text",
|
|
305
|
+
text: "Child item",
|
|
306
|
+
styles: {},
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
children: [],
|
|
310
|
+
props: {},
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
props: {},
|
|
314
|
+
},
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
const html = await exporter.toReactEmailDocument(nestedListDocument as any);
|
|
318
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterNestedLists");
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("should handle document with mixed content types", async () => {
|
|
322
|
+
const exporter = new ReactEmailExporter(
|
|
323
|
+
BlockNoteSchema.create(),
|
|
324
|
+
reactEmailDefaultSchemaMappings,
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
const mixedDocument = [
|
|
328
|
+
{
|
|
329
|
+
id: "1",
|
|
330
|
+
type: "heading",
|
|
331
|
+
content: [
|
|
332
|
+
{
|
|
333
|
+
type: "text",
|
|
334
|
+
text: "Main Heading",
|
|
335
|
+
styles: {},
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
children: [],
|
|
339
|
+
props: { level: 1 },
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: "2",
|
|
343
|
+
type: "paragraph",
|
|
344
|
+
content: [
|
|
345
|
+
{
|
|
346
|
+
type: "text",
|
|
347
|
+
text: "Regular paragraph with ",
|
|
348
|
+
styles: {},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
type: "text",
|
|
352
|
+
text: "bold text",
|
|
353
|
+
styles: { bold: true },
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
children: [],
|
|
357
|
+
props: {},
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: "3",
|
|
361
|
+
type: "numberedListItem",
|
|
362
|
+
content: [
|
|
363
|
+
{
|
|
364
|
+
type: "text",
|
|
365
|
+
text: "Numbered list item",
|
|
366
|
+
styles: {},
|
|
367
|
+
},
|
|
368
|
+
],
|
|
369
|
+
children: [],
|
|
370
|
+
props: {},
|
|
371
|
+
},
|
|
372
|
+
];
|
|
373
|
+
|
|
374
|
+
const html = await exporter.toReactEmailDocument(mixedDocument as any);
|
|
375
|
+
expect(html).toMatchSnapshot(
|
|
376
|
+
"__snapshots__/reactEmailExporterMixedContent",
|
|
377
|
+
);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it("should handle document with text alignment", async () => {
|
|
381
|
+
const exporter = new ReactEmailExporter(
|
|
382
|
+
BlockNoteSchema.create(),
|
|
383
|
+
reactEmailDefaultSchemaMappings,
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const alignedDocument = [
|
|
387
|
+
{
|
|
388
|
+
id: "1",
|
|
389
|
+
type: "paragraph",
|
|
390
|
+
content: [
|
|
391
|
+
{
|
|
392
|
+
type: "text",
|
|
393
|
+
text: "Center aligned text",
|
|
394
|
+
styles: {},
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
children: [],
|
|
398
|
+
props: { textAlignment: "center" },
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
id: "2",
|
|
402
|
+
type: "paragraph",
|
|
403
|
+
content: [
|
|
404
|
+
{
|
|
405
|
+
type: "text",
|
|
406
|
+
text: "Right aligned text",
|
|
407
|
+
styles: {},
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
children: [],
|
|
411
|
+
props: { textAlignment: "right" },
|
|
412
|
+
},
|
|
413
|
+
];
|
|
414
|
+
|
|
415
|
+
const html = await exporter.toReactEmailDocument(alignedDocument as any);
|
|
416
|
+
expect(html).toMatchSnapshot(
|
|
417
|
+
"__snapshots__/reactEmailExporterTextAlignment",
|
|
418
|
+
);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("should handle document with background colors", async () => {
|
|
422
|
+
const exporter = new ReactEmailExporter(
|
|
423
|
+
BlockNoteSchema.create(),
|
|
424
|
+
reactEmailDefaultSchemaMappings,
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const coloredDocument = [
|
|
428
|
+
{
|
|
429
|
+
id: "1",
|
|
430
|
+
type: "paragraph",
|
|
431
|
+
content: [
|
|
432
|
+
{
|
|
433
|
+
type: "text",
|
|
434
|
+
text: "Text with background color",
|
|
435
|
+
styles: {},
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
children: [],
|
|
439
|
+
props: { backgroundColor: "blue" },
|
|
440
|
+
},
|
|
441
|
+
];
|
|
442
|
+
|
|
443
|
+
const html = await exporter.toReactEmailDocument(coloredDocument as any);
|
|
444
|
+
|
|
445
|
+
expect(html).toMatchSnapshot(
|
|
446
|
+
"__snapshots__/reactEmailExporterBackgroundColor",
|
|
447
|
+
);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it("should handle document with text colors", async () => {
|
|
451
|
+
const exporter = new ReactEmailExporter(
|
|
452
|
+
BlockNoteSchema.create(),
|
|
453
|
+
reactEmailDefaultSchemaMappings,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
const coloredDocument = [
|
|
457
|
+
{
|
|
458
|
+
id: "1",
|
|
459
|
+
type: "paragraph",
|
|
460
|
+
content: [
|
|
461
|
+
{
|
|
462
|
+
type: "text",
|
|
463
|
+
text: "Colored text",
|
|
464
|
+
styles: {},
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
children: [],
|
|
468
|
+
props: { textColor: "red" },
|
|
469
|
+
},
|
|
470
|
+
];
|
|
471
|
+
|
|
472
|
+
const html = await exporter.toReactEmailDocument(coloredDocument as any);
|
|
473
|
+
|
|
474
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterTextColor");
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it("should handle document with code blocks", async () => {
|
|
478
|
+
const exporter = new ReactEmailExporter(
|
|
479
|
+
BlockNoteSchema.create(),
|
|
480
|
+
reactEmailDefaultSchemaMappings,
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
const codeDocument = [
|
|
484
|
+
{
|
|
485
|
+
id: "1",
|
|
486
|
+
type: "codeBlock",
|
|
487
|
+
content: [
|
|
488
|
+
{
|
|
489
|
+
type: "text",
|
|
490
|
+
text: "const hello = 'world';\nconsole.log(hello);",
|
|
491
|
+
styles: {},
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
children: [],
|
|
495
|
+
props: { language: "javascript" },
|
|
496
|
+
},
|
|
497
|
+
];
|
|
498
|
+
|
|
499
|
+
const html = await exporter.toReactEmailDocument(codeDocument as any);
|
|
500
|
+
|
|
501
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterCodeBlock");
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("should handle document with check list items", async () => {
|
|
505
|
+
const exporter = new ReactEmailExporter(
|
|
506
|
+
BlockNoteSchema.create(),
|
|
507
|
+
reactEmailDefaultSchemaMappings,
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
const checkListDocument = [
|
|
511
|
+
{
|
|
512
|
+
id: "1",
|
|
513
|
+
type: "checkListItem",
|
|
514
|
+
content: [
|
|
515
|
+
{
|
|
516
|
+
type: "text",
|
|
517
|
+
text: "Checked item",
|
|
518
|
+
styles: {},
|
|
519
|
+
},
|
|
520
|
+
],
|
|
521
|
+
children: [],
|
|
522
|
+
props: { checked: true },
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
id: "2",
|
|
526
|
+
type: "checkListItem",
|
|
527
|
+
content: [
|
|
528
|
+
{
|
|
529
|
+
type: "text",
|
|
530
|
+
text: "Unchecked item",
|
|
531
|
+
styles: {},
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
children: [],
|
|
535
|
+
props: { checked: false },
|
|
536
|
+
},
|
|
537
|
+
];
|
|
538
|
+
|
|
539
|
+
const html = await exporter.toReactEmailDocument(checkListDocument as any);
|
|
540
|
+
|
|
541
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterCheckList");
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it("should handle document with headings of different levels", async () => {
|
|
545
|
+
const exporter = new ReactEmailExporter(
|
|
546
|
+
BlockNoteSchema.create(),
|
|
547
|
+
reactEmailDefaultSchemaMappings,
|
|
548
|
+
);
|
|
549
|
+
|
|
550
|
+
const headingDocument = [
|
|
551
|
+
{
|
|
552
|
+
id: "1",
|
|
553
|
+
type: "heading",
|
|
554
|
+
content: [
|
|
555
|
+
{
|
|
556
|
+
type: "text",
|
|
557
|
+
text: "Heading 1",
|
|
558
|
+
styles: {},
|
|
559
|
+
},
|
|
560
|
+
],
|
|
561
|
+
children: [],
|
|
562
|
+
props: { level: 1 },
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
id: "2",
|
|
566
|
+
type: "heading",
|
|
567
|
+
content: [
|
|
568
|
+
{
|
|
569
|
+
type: "text",
|
|
570
|
+
text: "Heading 2",
|
|
571
|
+
styles: {},
|
|
572
|
+
},
|
|
573
|
+
],
|
|
574
|
+
children: [],
|
|
575
|
+
props: { level: 2 },
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
id: "3",
|
|
579
|
+
type: "heading",
|
|
580
|
+
content: [
|
|
581
|
+
{
|
|
582
|
+
type: "text",
|
|
583
|
+
text: "Heading 3",
|
|
584
|
+
styles: {},
|
|
585
|
+
},
|
|
586
|
+
],
|
|
587
|
+
children: [],
|
|
588
|
+
props: { level: 3 },
|
|
589
|
+
},
|
|
590
|
+
];
|
|
591
|
+
|
|
592
|
+
const html = await exporter.toReactEmailDocument(headingDocument as any);
|
|
593
|
+
|
|
594
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterHeadings");
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it("should handle document with complex nested structure", async () => {
|
|
598
|
+
const exporter = new ReactEmailExporter(
|
|
599
|
+
BlockNoteSchema.create(),
|
|
600
|
+
reactEmailDefaultSchemaMappings,
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
const complexDocument = [
|
|
604
|
+
{
|
|
605
|
+
id: "1",
|
|
606
|
+
type: "heading",
|
|
607
|
+
content: [
|
|
608
|
+
{
|
|
609
|
+
type: "text",
|
|
610
|
+
text: "Complex Document",
|
|
611
|
+
styles: { bold: true },
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
children: [],
|
|
615
|
+
props: { level: 1 },
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
id: "2",
|
|
619
|
+
type: "paragraph",
|
|
620
|
+
content: [
|
|
621
|
+
{
|
|
622
|
+
type: "text",
|
|
623
|
+
text: "This is a paragraph with ",
|
|
624
|
+
styles: {},
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
type: "text",
|
|
628
|
+
text: "bold",
|
|
629
|
+
styles: { bold: true },
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
type: "text",
|
|
633
|
+
text: " and ",
|
|
634
|
+
styles: {},
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
type: "text",
|
|
638
|
+
text: "italic",
|
|
639
|
+
styles: { italic: true },
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
type: "text",
|
|
643
|
+
text: " text, plus a ",
|
|
644
|
+
styles: {},
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
type: "link",
|
|
648
|
+
href: "https://example.com",
|
|
649
|
+
content: [
|
|
650
|
+
{
|
|
651
|
+
type: "text",
|
|
652
|
+
text: "link",
|
|
653
|
+
styles: {},
|
|
654
|
+
},
|
|
655
|
+
],
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
type: "text",
|
|
659
|
+
text: ".",
|
|
660
|
+
styles: {},
|
|
661
|
+
},
|
|
662
|
+
],
|
|
663
|
+
children: [],
|
|
664
|
+
props: { textAlignment: "center" },
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
id: "3",
|
|
668
|
+
type: "bulletListItem",
|
|
669
|
+
content: [
|
|
670
|
+
{
|
|
671
|
+
type: "text",
|
|
672
|
+
text: "List item with nested content",
|
|
673
|
+
styles: {},
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
children: [
|
|
677
|
+
{
|
|
678
|
+
id: "4",
|
|
679
|
+
type: "paragraph",
|
|
680
|
+
content: [
|
|
681
|
+
{
|
|
682
|
+
type: "text",
|
|
683
|
+
text: "Nested paragraph",
|
|
684
|
+
styles: {},
|
|
685
|
+
},
|
|
686
|
+
],
|
|
687
|
+
children: [],
|
|
688
|
+
props: {},
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
id: "5",
|
|
692
|
+
type: "numberedListItem",
|
|
693
|
+
content: [
|
|
694
|
+
{
|
|
695
|
+
type: "text",
|
|
696
|
+
text: "Nested numbered item",
|
|
697
|
+
styles: {},
|
|
698
|
+
},
|
|
699
|
+
],
|
|
700
|
+
children: [],
|
|
701
|
+
props: {},
|
|
702
|
+
},
|
|
703
|
+
],
|
|
704
|
+
props: {},
|
|
705
|
+
},
|
|
706
|
+
];
|
|
707
|
+
|
|
708
|
+
const html = await exporter.toReactEmailDocument(complexDocument as any);
|
|
709
|
+
|
|
710
|
+
expect(html).toMatchSnapshot(
|
|
711
|
+
"__snapshots__/reactEmailExporterComplexNested",
|
|
712
|
+
);
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
it("should handle document with mixed list types", async () => {
|
|
716
|
+
const exporter = new ReactEmailExporter(
|
|
717
|
+
BlockNoteSchema.create(),
|
|
718
|
+
reactEmailDefaultSchemaMappings,
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
const mixedListDocument = [
|
|
722
|
+
{
|
|
723
|
+
id: "1",
|
|
724
|
+
type: "bulletListItem",
|
|
725
|
+
content: [
|
|
726
|
+
{
|
|
727
|
+
type: "text",
|
|
728
|
+
text: "Bullet item 1",
|
|
729
|
+
styles: {},
|
|
730
|
+
},
|
|
731
|
+
],
|
|
732
|
+
children: [],
|
|
733
|
+
props: {},
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
id: "2",
|
|
737
|
+
type: "bulletListItem",
|
|
738
|
+
content: [
|
|
739
|
+
{
|
|
740
|
+
type: "text",
|
|
741
|
+
text: "Bullet item 2",
|
|
742
|
+
styles: {},
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
children: [],
|
|
746
|
+
props: {},
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
id: "3",
|
|
750
|
+
type: "numberedListItem",
|
|
751
|
+
content: [
|
|
752
|
+
{
|
|
753
|
+
type: "text",
|
|
754
|
+
text: "Numbered item 1",
|
|
755
|
+
styles: {},
|
|
756
|
+
},
|
|
757
|
+
],
|
|
758
|
+
children: [],
|
|
759
|
+
props: {},
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
id: "4",
|
|
763
|
+
type: "numberedListItem",
|
|
764
|
+
content: [
|
|
765
|
+
{
|
|
766
|
+
type: "text",
|
|
767
|
+
text: "Numbered item 2",
|
|
768
|
+
styles: {},
|
|
769
|
+
},
|
|
770
|
+
],
|
|
771
|
+
children: [],
|
|
772
|
+
props: {},
|
|
773
|
+
},
|
|
774
|
+
];
|
|
775
|
+
|
|
776
|
+
const html = await exporter.toReactEmailDocument(mixedListDocument as any);
|
|
777
|
+
|
|
778
|
+
expect(html).toMatchSnapshot("__snapshots__/reactEmailExporterMixedLists");
|
|
779
|
+
});
|
|
780
|
+
});
|