@blocknote/xl-pdf-exporter 0.21.0 → 0.23.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/dist/GeistMono-Regular-D4rKXxwr.js +5 -0
- package/dist/GeistMono-Regular-D4rKXxwr.js.map +1 -0
- package/dist/blocknote-xl-pdf-exporter.js +228 -2293
- package/dist/blocknote-xl-pdf-exporter.js.map +1 -1
- package/dist/blocknote-xl-pdf-exporter.umd.cjs +2 -68
- package/dist/blocknote-xl-pdf-exporter.umd.cjs.map +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +5 -4
- package/src/pdf/__snapshots__/example.jsx +910 -567
- package/src/pdf/__snapshots__/exampleWithHeaderAndFooter.jsx +934 -576
- package/src/pdf/defaultSchema/blocks.tsx +35 -2
- package/src/pdf/defaultSchema/styles.tsx +1 -1
- package/src/pdf/pdfExporter.test.tsx +12 -7
- package/src/pdf/pdfExporter.tsx +14 -4
- package/types/src/pdf/defaultSchema/blocks.d.ts +2 -2
- package/types/src/pdf/defaultSchema/index.d.ts +25 -0
- package/types/src/pdf/pdfExporter.d.ts +0 -1
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
BlockMapping,
|
|
3
3
|
DefaultBlockSchema,
|
|
4
4
|
DefaultProps,
|
|
5
|
+
pageBreakSchema,
|
|
6
|
+
StyledText,
|
|
5
7
|
} from "@blocknote/core";
|
|
6
8
|
import { Image, Link, Path, Svg, Text, View } from "@react-pdf/renderer";
|
|
7
9
|
import {
|
|
@@ -16,7 +18,7 @@ const PIXELS_PER_POINT = 0.75;
|
|
|
16
18
|
const FONT_SIZE = 16;
|
|
17
19
|
|
|
18
20
|
export const pdfBlockMappingForDefaultSchema: BlockMapping<
|
|
19
|
-
DefaultBlockSchema,
|
|
21
|
+
DefaultBlockSchema & typeof pageBreakSchema.blockSchema,
|
|
20
22
|
any,
|
|
21
23
|
any,
|
|
22
24
|
React.ReactElement<Text>,
|
|
@@ -69,7 +71,38 @@ export const pdfBlockMappingForDefaultSchema: BlockMapping<
|
|
|
69
71
|
);
|
|
70
72
|
},
|
|
71
73
|
codeBlock: (block) => {
|
|
72
|
-
|
|
74
|
+
const textContent = (block.content as StyledText<any>[])[0]?.text || "";
|
|
75
|
+
const lines = textContent.split("\n").map((line, index) => {
|
|
76
|
+
const indent = line.match(/^\s*/)?.[0].length || 0;
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<Text
|
|
80
|
+
key={`line_${index}`}
|
|
81
|
+
style={{
|
|
82
|
+
marginLeft: indent * 9.5 * PIXELS_PER_POINT,
|
|
83
|
+
}}>
|
|
84
|
+
{line.trimStart() || <> </>}
|
|
85
|
+
</Text>
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<View
|
|
91
|
+
wrap={false}
|
|
92
|
+
style={{
|
|
93
|
+
padding: 24 * PIXELS_PER_POINT,
|
|
94
|
+
backgroundColor: "#161616",
|
|
95
|
+
color: "#ffffff",
|
|
96
|
+
lineHeight: 1.25,
|
|
97
|
+
fontSize: FONT_SIZE * PIXELS_PER_POINT,
|
|
98
|
+
fontFamily: "GeistMono",
|
|
99
|
+
}}>
|
|
100
|
+
{lines}
|
|
101
|
+
</View>
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
pageBreak: () => {
|
|
105
|
+
return <View break />;
|
|
73
106
|
},
|
|
74
107
|
audio: (block, exporter) => {
|
|
75
108
|
return (
|
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
defaultBlockSpecs,
|
|
7
7
|
defaultInlineContentSpecs,
|
|
8
8
|
defaultStyleSpecs,
|
|
9
|
+
PageBreak,
|
|
9
10
|
} from "@blocknote/core";
|
|
10
11
|
import { Text } from "@react-pdf/renderer";
|
|
11
12
|
import { testDocument } from "@shared/testDocument.js";
|
|
12
|
-
import
|
|
13
|
+
import reactElementToJSXString from "react-element-to-jsx-string";
|
|
13
14
|
import { describe, expect, it } from "vitest";
|
|
14
15
|
import { pdfDefaultSchemaMappings } from "./defaultSchema/index.js";
|
|
15
16
|
import { PDFExporter } from "./pdfExporter.js";
|
|
@@ -26,6 +27,7 @@ describe("exporter", () => {
|
|
|
26
27
|
const schema = BlockNoteSchema.create({
|
|
27
28
|
blockSpecs: {
|
|
28
29
|
...defaultBlockSpecs,
|
|
30
|
+
pageBreak: PageBreak,
|
|
29
31
|
extraBlock: createBlockSpec(
|
|
30
32
|
{
|
|
31
33
|
content: "none",
|
|
@@ -155,13 +157,15 @@ describe("exporter", () => {
|
|
|
155
157
|
|
|
156
158
|
it("should export a document", async () => {
|
|
157
159
|
const exporter = new PDFExporter(
|
|
158
|
-
BlockNoteSchema.create(
|
|
160
|
+
BlockNoteSchema.create({
|
|
161
|
+
blockSpecs: { ...defaultBlockSpecs, pageBreak: PageBreak },
|
|
162
|
+
}),
|
|
159
163
|
pdfDefaultSchemaMappings
|
|
160
164
|
);
|
|
161
165
|
|
|
162
166
|
const transformed = await exporter.toReactPDFDocument(testDocument);
|
|
163
|
-
const
|
|
164
|
-
|
|
167
|
+
const str = reactElementToJSXString(transformed);
|
|
168
|
+
|
|
165
169
|
expect(str).toMatchFileSnapshot("__snapshots__/example.jsx");
|
|
166
170
|
|
|
167
171
|
// would be nice to compare pdf images, but currently doesn't work on mac os (due to node canvas installation issue)
|
|
@@ -186,7 +190,9 @@ describe("exporter", () => {
|
|
|
186
190
|
|
|
187
191
|
it("should export a document with header and footer", async () => {
|
|
188
192
|
const exporter = new PDFExporter(
|
|
189
|
-
BlockNoteSchema.create(
|
|
193
|
+
BlockNoteSchema.create({
|
|
194
|
+
blockSpecs: { ...defaultBlockSpecs, pageBreak: PageBreak },
|
|
195
|
+
}),
|
|
190
196
|
pdfDefaultSchemaMappings
|
|
191
197
|
);
|
|
192
198
|
|
|
@@ -194,8 +200,7 @@ describe("exporter", () => {
|
|
|
194
200
|
header: <Text>Header</Text>,
|
|
195
201
|
footer: <Text>Footer</Text>,
|
|
196
202
|
});
|
|
197
|
-
const
|
|
198
|
-
const str = prettyDOM(view.container, undefined, { highlight: false });
|
|
203
|
+
const str = reactElementToJSXString(transformed);
|
|
199
204
|
expect(str).toMatchFileSnapshot(
|
|
200
205
|
"__snapshots__/exampleWithHeaderAndFooter.jsx"
|
|
201
206
|
);
|
package/src/pdf/pdfExporter.tsx
CHANGED
|
@@ -63,7 +63,6 @@ export class PDFExporter<
|
|
|
63
63
|
fontSize: FONT_SIZE * PIXELS_PER_POINT, // pixels
|
|
64
64
|
lineHeight: 1.5,
|
|
65
65
|
},
|
|
66
|
-
section: {},
|
|
67
66
|
block: {},
|
|
68
67
|
blockChildren: {},
|
|
69
68
|
header: {},
|
|
@@ -145,6 +144,11 @@ export class PDFExporter<
|
|
|
145
144
|
numberedListIndex
|
|
146
145
|
); // TODO: any
|
|
147
146
|
|
|
147
|
+
if (b.type === "pageBreak") {
|
|
148
|
+
ret.push(self);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
148
152
|
const style = this.blocknoteDefaultPropsToReactPDFStyle(b.props as any);
|
|
149
153
|
ret.push(
|
|
150
154
|
<>
|
|
@@ -216,6 +220,14 @@ export class PDFExporter<
|
|
|
216
220
|
fontWeight: "bold",
|
|
217
221
|
});
|
|
218
222
|
|
|
223
|
+
font = await loadFontDataUrl(
|
|
224
|
+
await import("@shared/assets/fonts/GeistMono-Regular.ttf")
|
|
225
|
+
);
|
|
226
|
+
Font.register({
|
|
227
|
+
family: "GeistMono",
|
|
228
|
+
src: font,
|
|
229
|
+
});
|
|
230
|
+
|
|
219
231
|
this.fontsRegistered = true;
|
|
220
232
|
}
|
|
221
233
|
|
|
@@ -247,9 +259,7 @@ export class PDFExporter<
|
|
|
247
259
|
{options.header}
|
|
248
260
|
</View>
|
|
249
261
|
)}
|
|
250
|
-
|
|
251
|
-
{await this.transformBlocks(blocks)}
|
|
252
|
-
</View>
|
|
262
|
+
{await this.transformBlocks(blocks)}
|
|
253
263
|
{options.footer && (
|
|
254
264
|
<View
|
|
255
265
|
fixed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { BlockMapping, DefaultBlockSchema } from "@blocknote/core";
|
|
2
|
+
import { BlockMapping, DefaultBlockSchema, pageBreakSchema } from "@blocknote/core";
|
|
3
3
|
import { Link, Text } from "@react-pdf/renderer";
|
|
4
|
-
export declare const pdfBlockMappingForDefaultSchema: BlockMapping<DefaultBlockSchema, any, any, React.ReactElement<Text>, React.ReactElement<Text> | React.ReactElement<Link>>;
|
|
4
|
+
export declare const pdfBlockMappingForDefaultSchema: BlockMapping<DefaultBlockSchema & typeof pageBreakSchema.blockSchema, any, any, React.ReactElement<Text>, React.ReactElement<Text> | React.ReactElement<Link>>;
|
|
@@ -138,6 +138,10 @@ export declare const pdfDefaultSchemaMappings: {
|
|
|
138
138
|
type: "numberedListItem";
|
|
139
139
|
content: "inline";
|
|
140
140
|
propSchema: {
|
|
141
|
+
start: {
|
|
142
|
+
default: undefined;
|
|
143
|
+
type: "number";
|
|
144
|
+
};
|
|
141
145
|
backgroundColor: {
|
|
142
146
|
default: "default";
|
|
143
147
|
};
|
|
@@ -154,6 +158,10 @@ export declare const pdfDefaultSchemaMappings: {
|
|
|
154
158
|
type: "numberedListItem";
|
|
155
159
|
content: "inline";
|
|
156
160
|
propSchema: {
|
|
161
|
+
start: {
|
|
162
|
+
default: undefined;
|
|
163
|
+
type: "number";
|
|
164
|
+
};
|
|
157
165
|
backgroundColor: {
|
|
158
166
|
default: "default";
|
|
159
167
|
};
|
|
@@ -439,6 +447,23 @@ export declare const pdfDefaultSchemaMappings: {
|
|
|
439
447
|
fileBlockAccept: string[];
|
|
440
448
|
}, any, import("@blocknote/core").InlineContentSchema, import("@blocknote/core").StyleSchema>;
|
|
441
449
|
};
|
|
450
|
+
}> & import("@blocknote/core").BlockSchemaFromSpecs<{
|
|
451
|
+
pageBreak: {
|
|
452
|
+
config: {
|
|
453
|
+
type: "pageBreak";
|
|
454
|
+
propSchema: {};
|
|
455
|
+
content: "none";
|
|
456
|
+
isFileBlock: false;
|
|
457
|
+
isSelectable: false;
|
|
458
|
+
};
|
|
459
|
+
implementation: import("@blocknote/core").TiptapBlockImplementation<{
|
|
460
|
+
type: "pageBreak";
|
|
461
|
+
propSchema: {};
|
|
462
|
+
content: "none";
|
|
463
|
+
isFileBlock: false;
|
|
464
|
+
isSelectable: false;
|
|
465
|
+
}, any, import("@blocknote/core").InlineContentSchema, import("@blocknote/core").StyleSchema>;
|
|
466
|
+
};
|
|
442
467
|
}>, any, any, import("react").ReactElement<import("@react-pdf/renderer").Text, string | import("react").JSXElementConstructor<any>>, import("react").ReactElement<import("@react-pdf/renderer").Text, string | import("react").JSXElementConstructor<any>> | import("react").ReactElement<import("@react-pdf/renderer").Link, string | import("react").JSXElementConstructor<any>>>;
|
|
443
468
|
inlineContentMapping: import("@blocknote/core").InlineContentMapping<import("@blocknote/core").InlineContentSchemaFromSpecs<{
|
|
444
469
|
text: {
|