@blocknote/xl-pdf-exporter 0.19.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.
Files changed (78) hide show
  1. package/LICENSE +661 -0
  2. package/dist/Inter_18pt-Bold-BOnnSImi.js +5 -0
  3. package/dist/Inter_18pt-Bold-BOnnSImi.js.map +1 -0
  4. package/dist/Inter_18pt-BoldItalic-DPKIpVzB.js +5 -0
  5. package/dist/Inter_18pt-BoldItalic-DPKIpVzB.js.map +1 -0
  6. package/dist/Inter_18pt-Italic-BVnfHlUD.js +5 -0
  7. package/dist/Inter_18pt-Italic-BVnfHlUD.js.map +1 -0
  8. package/dist/Inter_18pt-Regular-byxnNS-8.js +5 -0
  9. package/dist/Inter_18pt-Regular-byxnNS-8.js.map +1 -0
  10. package/dist/blocknote-xl-pdf-exporter.js +2503 -0
  11. package/dist/blocknote-xl-pdf-exporter.js.map +1 -0
  12. package/dist/blocknote-xl-pdf-exporter.umd.cjs +69 -0
  13. package/dist/blocknote-xl-pdf-exporter.umd.cjs.map +1 -0
  14. package/dist/webpack-stats.json +1 -0
  15. package/package.json +88 -0
  16. package/src/index.ts +1 -0
  17. package/src/pdf/__snapshots__/example.jsx +592 -0
  18. package/src/pdf/__snapshots__/exampleWithHeaderAndFooter.jsx +602 -0
  19. package/src/pdf/defaultSchema/blocks.tsx +177 -0
  20. package/src/pdf/defaultSchema/index.ts +9 -0
  21. package/src/pdf/defaultSchema/inlinecontent.tsx +23 -0
  22. package/src/pdf/defaultSchema/styles.tsx +68 -0
  23. package/src/pdf/index.ts +2 -0
  24. package/src/pdf/pdfExporter.test.tsx +208 -0
  25. package/src/pdf/pdfExporter.tsx +297 -0
  26. package/src/pdf/types.ts +3 -0
  27. package/src/pdf/util/listItem.tsx +70 -0
  28. package/src/pdf/util/table/Table.tsx +76 -0
  29. package/src/vite-env.d.ts +11 -0
  30. package/types/src/Exporter.d.ts +26 -0
  31. package/types/src/context/BlockNoteContext.d.ts +59 -0
  32. package/types/src/context/BlockNoteContext.test.d.ts +1 -0
  33. package/types/src/context/ServerBlockNoteEditor.d.ts +137 -0
  34. package/types/src/context/ServerBlockNoteEditor.test.d.ts +1 -0
  35. package/types/src/context/react/ReactServer.test.d.ts +2 -0
  36. package/types/src/docx/blocks.d.ts +433 -0
  37. package/types/src/docx/defaultSchema/blocks.d.ts +4 -0
  38. package/types/src/docx/defaultSchema/index.d.ts +559 -0
  39. package/types/src/docx/defaultSchema/inlinecontent.d.ts +4 -0
  40. package/types/src/docx/defaultSchema/styles.d.ts +4 -0
  41. package/types/src/docx/docxExporter.d.ts +14 -0
  42. package/types/src/docx/docxExporter.test.d.ts +1 -0
  43. package/types/src/docx/imageUtil.d.ts +4 -0
  44. package/types/src/docx/index.d.ts +2 -0
  45. package/types/src/docx/inlinecontent.d.ts +12 -0
  46. package/types/src/docx/styles.d.ts +55 -0
  47. package/types/src/docx/util/Table.d.ts +4 -0
  48. package/types/src/docxExporter.d.ts +255 -0
  49. package/types/src/docxExporter.test.d.ts +1 -0
  50. package/types/src/index.d.ts +1 -0
  51. package/types/src/mapping.d.ts +29 -0
  52. package/types/src/pdf/blocks.d.ts +434 -0
  53. package/types/src/pdf/defaultSchema/blocks.d.ts +4 -0
  54. package/types/src/pdf/defaultSchema/index.d.ts +510 -0
  55. package/types/src/pdf/defaultSchema/inlinecontent.d.ts +4 -0
  56. package/types/src/pdf/defaultSchema/styles.d.ts +3 -0
  57. package/types/src/pdf/index.d.ts +2 -0
  58. package/types/src/pdf/inlinecontent.d.ts +13 -0
  59. package/types/src/pdf/pdfExporter.d.ts +81 -0
  60. package/types/src/pdf/pdfExporter.test.d.ts +1 -0
  61. package/types/src/pdf/styles.d.ts +55 -0
  62. package/types/src/pdf/types.d.ts +2 -0
  63. package/types/src/pdf/util/listItem.d.ts +9 -0
  64. package/types/src/pdf/util/loadFontDataUrl.d.ts +3 -0
  65. package/types/src/pdf/util/table/Table.d.ts +5 -0
  66. package/types/src/pdfExporter.d.ts +256 -0
  67. package/types/src/pdfExporter.test.d.ts +1 -0
  68. package/types/src/react-email/defaultSchema/blocks.d.ts +5 -0
  69. package/types/src/react-email/defaultSchema/index.d.ts +560 -0
  70. package/types/src/react-email/defaultSchema/inlinecontent.d.ts +5 -0
  71. package/types/src/react-email/defaultSchema/styles.d.ts +4 -0
  72. package/types/src/react-email/reactEmailExporter.d.ts +13 -0
  73. package/types/src/react-email/reactEmailExporter.test.d.ts +8 -0
  74. package/types/src/testDocument.d.ts +505 -0
  75. package/types/src/transformer.d.ts +20 -0
  76. package/types/src/util/fileUtil.d.ts +22 -0
  77. package/types/src/util/imageUtil.d.ts +4 -0
  78. package/types/src/yjs/index.d.ts +2 -0
@@ -0,0 +1,297 @@
1
+ import {
2
+ Block,
3
+ BlockNoteSchema,
4
+ BlockSchema,
5
+ COLORS_DEFAULT,
6
+ DefaultProps,
7
+ Exporter,
8
+ ExporterOptions,
9
+ InlineContentSchema,
10
+ StyleSchema,
11
+ StyledText,
12
+ } from "@blocknote/core";
13
+ import {
14
+ Document,
15
+ Font,
16
+ Link,
17
+ Page,
18
+ StyleSheet,
19
+ Text,
20
+ TextProps,
21
+ View,
22
+ } from "@react-pdf/renderer";
23
+ import { corsProxyResolveFileUrl } from "@shared/api/corsProxy.js";
24
+ import { loadFontDataUrl } from "../../../../shared/util/fileUtil.js";
25
+
26
+ import { Style } from "./types.js";
27
+
28
+ const FONT_SIZE = 16;
29
+ const PIXELS_PER_POINT = 0.75;
30
+
31
+ type Options = ExporterOptions & {
32
+ /**
33
+ *
34
+ * @default uses the remote emoji source hosted on cloudflare (https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/)
35
+ */
36
+ emojiSource: false | ReturnType<typeof Font.getEmojiSource>;
37
+ };
38
+
39
+ /**
40
+ * Exports a BlockNote document to a .pdf file using the react-pdf library.
41
+ */
42
+ export class PDFExporter<
43
+ B extends BlockSchema,
44
+ S extends StyleSchema,
45
+ I extends InlineContentSchema
46
+ > extends Exporter<
47
+ B,
48
+ I,
49
+ S,
50
+ React.ReactElement<Text>,
51
+ React.ReactElement<Link> | React.ReactElement<Text>,
52
+ TextProps["style"],
53
+ React.ReactElement<Text>
54
+ > {
55
+ private fontsRegistered = false;
56
+
57
+ public styles = StyleSheet.create({
58
+ page: {
59
+ paddingTop: 35,
60
+ paddingBottom: 65,
61
+ paddingHorizontal: 35,
62
+ fontFamily: "Inter",
63
+ fontSize: FONT_SIZE * PIXELS_PER_POINT, // pixels
64
+ lineHeight: 1.5,
65
+ },
66
+ section: {},
67
+ block: {},
68
+ blockChildren: {},
69
+ header: {},
70
+ footer: {
71
+ // @ts-ignore
72
+ position: "absolute",
73
+ },
74
+ });
75
+
76
+ public readonly options: Options;
77
+
78
+ public constructor(
79
+ /**
80
+ * The schema of your editor. The mappings are automatically typed checked against this schema.
81
+ */
82
+ protected readonly schema: BlockNoteSchema<B, I, S>,
83
+ /**
84
+ * The mappings that map the BlockNote schema to the react-pdf content.
85
+ *
86
+ * Pass {@link pdfDefaultSchemaMappings} for the default schema.
87
+ */
88
+ mappings: Exporter<
89
+ NoInfer<B>,
90
+ NoInfer<I>,
91
+ NoInfer<S>,
92
+ React.ReactElement<Text>, // RB
93
+ React.ReactElement<Link> | React.ReactElement<Text>, // RI
94
+ TextProps["style"], // RS
95
+ React.ReactElement<Text> // TS
96
+ >["mappings"],
97
+ options?: Partial<Options>
98
+ ) {
99
+ const defaults = {
100
+ emojiSource: {
101
+ format: "png",
102
+ url: "https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/",
103
+ },
104
+ resolveFileUrl: corsProxyResolveFileUrl,
105
+ colors: COLORS_DEFAULT,
106
+ } satisfies Partial<Options>;
107
+
108
+ const newOptions = {
109
+ ...defaults,
110
+ ...options,
111
+ };
112
+ super(schema, mappings, newOptions);
113
+ this.options = newOptions;
114
+ }
115
+
116
+ /**
117
+ * Mostly for internal use, you probably want to use `toBlob` or `toReactPDFDocument` instead.
118
+ */
119
+ public transformStyledText(styledText: StyledText<S>) {
120
+ const stylesArray = this.mapStyles(styledText.styles);
121
+ const styles = Object.assign({}, ...stylesArray);
122
+ return <Text style={styles}>{styledText.text}</Text>;
123
+ }
124
+
125
+ /**
126
+ * Mostly for internal use, you probably want to use `toBlob` or `toReactPDFDocument` instead.
127
+ */
128
+ public async transformBlocks(
129
+ blocks: Block<B, I, S>[], // Or BlockFromConfig<B[keyof B], I, S>?
130
+ nestingLevel = 0
131
+ ): Promise<React.ReactElement<Text>[]> {
132
+ const ret: React.ReactElement<Text>[] = [];
133
+ let numberedListIndex = 0;
134
+
135
+ for (const b of blocks) {
136
+ if (b.type === "numberedListItem") {
137
+ numberedListIndex++;
138
+ } else {
139
+ numberedListIndex = 0;
140
+ }
141
+ const children = await this.transformBlocks(b.children, nestingLevel + 1);
142
+ const self = await this.mapBlock(
143
+ b as any,
144
+ nestingLevel,
145
+ numberedListIndex
146
+ ); // TODO: any
147
+
148
+ const style = this.blocknoteDefaultPropsToReactPDFStyle(b.props as any);
149
+ ret.push(
150
+ <>
151
+ <View
152
+ style={{
153
+ paddingVertical: 3 * PIXELS_PER_POINT,
154
+ ...this.styles.block,
155
+ ...style,
156
+ }}>
157
+ {self}
158
+ </View>
159
+ {children.length > 0 && (
160
+ <View
161
+ style={{
162
+ marginLeft: FONT_SIZE * 1.5 * PIXELS_PER_POINT,
163
+ ...this.styles.blockChildren,
164
+ }}>
165
+ {children}
166
+ </View>
167
+ )}
168
+ </>
169
+ );
170
+ }
171
+
172
+ return ret;
173
+ }
174
+
175
+ protected async registerFonts() {
176
+ if (this.fontsRegistered) {
177
+ return;
178
+ }
179
+
180
+ if (this.options.emojiSource) {
181
+ Font.registerEmojiSource(this.options.emojiSource);
182
+ }
183
+ let font = await loadFontDataUrl(
184
+ await import("@shared/assets/fonts/inter/Inter_18pt-Regular.ttf")
185
+ );
186
+ Font.register({
187
+ family: "Inter",
188
+ src: font,
189
+ });
190
+
191
+ font = await loadFontDataUrl(
192
+ await import("@shared/assets/fonts/inter/Inter_18pt-Italic.ttf")
193
+ );
194
+ Font.register({
195
+ family: "Inter",
196
+ fontStyle: "italic",
197
+ src: font,
198
+ });
199
+
200
+ font = await loadFontDataUrl(
201
+ await import("@shared/assets/fonts/inter/Inter_18pt-Bold.ttf")
202
+ );
203
+ Font.register({
204
+ family: "Inter",
205
+ src: font,
206
+ fontWeight: "bold",
207
+ });
208
+
209
+ font = await loadFontDataUrl(
210
+ await import("@shared/assets/fonts/inter/Inter_18pt-BoldItalic.ttf")
211
+ );
212
+ Font.register({
213
+ family: "Inter",
214
+ fontStyle: "italic",
215
+ src: font,
216
+ fontWeight: "bold",
217
+ });
218
+
219
+ this.fontsRegistered = true;
220
+ }
221
+
222
+ /**
223
+ * Convert a document (array of Blocks) to a react-pdf Document.
224
+ */
225
+ public async toReactPDFDocument(
226
+ blocks: Block<B, I, S>[],
227
+ options: {
228
+ /**
229
+ * Add a header to every page.
230
+ * The React component passed must be a React-PDF component
231
+ */
232
+ header?: React.ReactElement;
233
+ /**
234
+ * Add a footer to every page.
235
+ * The React component passed must be a React-PDF component
236
+ */
237
+ footer?: React.ReactElement;
238
+ } = {}
239
+ ) {
240
+ await this.registerFonts();
241
+
242
+ return (
243
+ <Document>
244
+ <Page dpi={100} size="A4" style={this.styles.page}>
245
+ {options.header && (
246
+ <View fixed style={this.styles.header}>
247
+ {options.header}
248
+ </View>
249
+ )}
250
+ <View style={this.styles.section}>
251
+ {await this.transformBlocks(blocks)}
252
+ </View>
253
+ {options.footer && (
254
+ <View
255
+ fixed
256
+ style={[
257
+ {
258
+ left: this.styles.page.paddingHorizontal || 0,
259
+ bottom: (this.styles.page.paddingBottom || 0) / 2,
260
+ right: this.styles.page.paddingHorizontal || 0,
261
+ },
262
+ this.styles.footer,
263
+ ]}>
264
+ {options.footer}
265
+ </View>
266
+ )}
267
+ </Page>
268
+ </Document>
269
+ );
270
+ }
271
+
272
+ protected blocknoteDefaultPropsToReactPDFStyle(
273
+ props: Partial<DefaultProps>
274
+ ): Style {
275
+ return {
276
+ textAlign: props.textAlignment,
277
+ backgroundColor:
278
+ props.backgroundColor === "default" || !props.backgroundColor
279
+ ? undefined
280
+ : this.options.colors[
281
+ props.backgroundColor as keyof typeof this.options.colors
282
+ ].background,
283
+ color:
284
+ props.textColor === "default" || !props.textColor
285
+ ? undefined
286
+ : this.options.colors[
287
+ props.textColor as keyof typeof this.options.colors
288
+ ].text,
289
+ alignItems:
290
+ props.textAlignment === "right"
291
+ ? "flex-end"
292
+ : props.textAlignment === "center"
293
+ ? "center"
294
+ : undefined,
295
+ };
296
+ }
297
+ }
@@ -0,0 +1,3 @@
1
+ import { Styles } from "@react-pdf/renderer";
2
+
3
+ export type Style = Styles[keyof Styles];
@@ -0,0 +1,70 @@
1
+ import { Path, StyleSheet, Svg, Text, View } from "@react-pdf/renderer";
2
+ import { Style } from "../types.js";
3
+
4
+ // https://github.com/diegomura/react-pdf/issues/134
5
+
6
+ const PIXELS_PER_POINT = 0.75;
7
+
8
+ const styles = StyleSheet.create({
9
+ listItem: {
10
+ display: "flex",
11
+ flexDirection: "row",
12
+ gap: 8 * PIXELS_PER_POINT,
13
+ paddingRight: 10, // otherwise text overflows, seems like a react-pdf / yoga bug
14
+ },
15
+ bullet: {
16
+ fontFamily: "", // TODO: add symbol font
17
+ },
18
+ });
19
+
20
+ export const BULLET_MARKER = "\u2022";
21
+
22
+ // https://fonts.google.com/icons?selected=Material+Symbols+Outlined:check_box_outline_blank:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=undefined
23
+ export const CHECK_MARKER_UNCHECKED = (
24
+ <Svg
25
+ style={{ marginTop: 2 }}
26
+ height="12"
27
+ viewBox="0 -960 960 960"
28
+ width="12"
29
+ fill="undefined">
30
+ <Path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Z" />
31
+ </Svg>
32
+ );
33
+
34
+ // https://fonts.google.com/icons?selected=Material+Symbols+Outlined:check_box:FILL@0;wght@400;GRAD@0;opsz@24&icon.size=24&icon.color=undefined
35
+ export const CHECK_MARKER_CHECKED = (
36
+ <Svg
37
+ style={{ marginTop: 2 }}
38
+ height="12"
39
+ viewBox="0 -960 960 960"
40
+ width="12"
41
+ fill="undefined">
42
+ <Path d="m424-312 282-282-56-56-226 226-114-114-56 56 170 170ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z" />
43
+ </Svg>
44
+ );
45
+
46
+ export const ListItem = ({
47
+ listMarker,
48
+ children,
49
+ style,
50
+ }: {
51
+ listMarker: string | React.ReactNode;
52
+ children: React.ReactNode;
53
+ style?: Style;
54
+ }) => {
55
+ return (
56
+ <View style={[styles.listItem, style || {}]}>
57
+ <View style={styles.bullet}>
58
+ {/* <Svg width={2} height={2}>
59
+ <Circle cx="1" cy="1" r="2" fill="black" />
60
+ </Svg> */}
61
+ {typeof listMarker === "string" ? (
62
+ <Text>{listMarker}</Text>
63
+ ) : (
64
+ listMarker
65
+ )}
66
+ </View>
67
+ {children}
68
+ </View>
69
+ );
70
+ };
@@ -0,0 +1,76 @@
1
+ import {
2
+ Exporter,
3
+ InlineContentSchema,
4
+ StyleSchema,
5
+ TableContent,
6
+ } from "@blocknote/core";
7
+ import { StyleSheet, View } from "@react-pdf/renderer";
8
+ const PIXELS_PER_POINT = 0.75;
9
+
10
+ // ( impossible?) to make tables with flex that don't have a fixed / 100% width?
11
+ // we'd need to measure the width of every column manually
12
+ const styles = StyleSheet.create({
13
+ tableContainer: {
14
+ // width: "100%",
15
+ },
16
+ row: {
17
+ flexDirection: "row",
18
+ flexWrap: "wrap",
19
+ // width: "100%",
20
+ // justifyContent: "space-between",
21
+ display: "flex",
22
+ },
23
+ cell: {
24
+ paddingHorizontal: 5 * PIXELS_PER_POINT,
25
+ paddingTop: 3 * PIXELS_PER_POINT,
26
+ // paddingBottom: 1 * PIXELS_PER_POINT, should be 3px but looks odd, better with no padding Bottom
27
+ borderLeft: "1px solid #ddd",
28
+ borderTop: "1px solid #ddd",
29
+ wordWrap: "break-word",
30
+ whiteSpace: "pre-wrap",
31
+ },
32
+ bottomCell: {
33
+ borderBottom: "1px solid #ddd",
34
+ },
35
+ rightCell: {
36
+ borderRight: "1px solid #ddd",
37
+ },
38
+ });
39
+
40
+ export const Table = (props: {
41
+ data: TableContent<InlineContentSchema>;
42
+ transformer: Exporter<
43
+ any,
44
+ InlineContentSchema,
45
+ StyleSchema,
46
+ any,
47
+ any,
48
+ any,
49
+ any
50
+ >;
51
+ }) => (
52
+ <View style={styles.tableContainer} wrap={false}>
53
+ {props.data.rows.map((row, index) => (
54
+ <View
55
+ style={[
56
+ styles.row,
57
+ index === props.data.rows.length - 1 ? styles.bottomCell : {},
58
+ ]}
59
+ key={index}>
60
+ {row.cells.map((cell, index) => (
61
+ <View
62
+ style={[
63
+ styles.cell,
64
+ index === row.cells.length - 1 ? styles.rightCell : {},
65
+ props.data.columnWidths[index]
66
+ ? { width: props.data.columnWidths[index] }
67
+ : { flex: 1 },
68
+ ]}
69
+ key={index}>
70
+ {props.transformer.transformInlineContent(cell)}
71
+ </View>
72
+ ))}
73
+ </View>
74
+ ))}
75
+ </View>
76
+ );
@@ -0,0 +1,11 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
4
+ interface ImportMetaEnv {
5
+ // readonly VITE_APP_TITLE: string;
6
+ // more env variables...
7
+ }
8
+
9
+ interface ImportMeta {
10
+ readonly env: ImportMetaEnv;
11
+ }
@@ -0,0 +1,26 @@
1
+ import { BlockFromConfig, BlockNoteSchema, BlockSchema, COLORS_DEFAULT, InlineContent, InlineContentSchema, StyleSchema, StyledText, Styles } from "@blocknote/core";
2
+ import { BlockMapping, InlineContentMapping, StyleMapping } from "./mapping.js";
3
+ export type ExporterOptions = {
4
+ resolveFileUrl?: (url: string) => Promise<string | Blob>;
5
+ colors: typeof COLORS_DEFAULT;
6
+ };
7
+ export declare abstract class Exporter<B extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema, RB, RI, RS, TS> {
8
+ readonly mappings: {
9
+ blockMapping: BlockMapping<B, I, S, RB, RI>;
10
+ inlineContentMapping: InlineContentMapping<I, S, RI, TS>;
11
+ styleMapping: StyleMapping<S, RS>;
12
+ };
13
+ readonly options: ExporterOptions;
14
+ constructor(_schema: BlockNoteSchema<B, I, S>, // only used for type inference
15
+ mappings: {
16
+ blockMapping: BlockMapping<B, I, S, RB, RI>;
17
+ inlineContentMapping: InlineContentMapping<I, S, RI, TS>;
18
+ styleMapping: StyleMapping<S, RS>;
19
+ }, options: ExporterOptions);
20
+ resolveFile(url: string): Promise<Blob>;
21
+ mapStyles(styles: Styles<S>): RS[];
22
+ mapInlineContent(inlineContent: InlineContent<I, S>): RI;
23
+ transformInlineContent(inlineContentArray: InlineContent<I, S>[]): RI[];
24
+ abstract transformStyledText(styledText: StyledText<S>): TS;
25
+ mapBlock(block: BlockFromConfig<B[keyof B], I, S>, nestingLevel: number, numberedListIndex: number): Promise<RB>;
26
+ }
@@ -0,0 +1,59 @@
1
+ import { Block, BlockSchema, BlockSchemaFromSpecs, BlockSpecs, DefaultBlockSchema, DefaultInlineContentSchema, DefaultStyleSchema, InlineContentSchema, InlineContentSchemaFromSpecs, InlineContentSpecs, StyleSchema, StyleSchemaFromSpecs, StyleSpecs, defaultBlockSpecs, defaultInlineContentSpecs, defaultStyleSpecs } from "@blocknote/core";
2
+ import { Schema as PMSchema } from "@tiptap/pm/model";
3
+ import * as Y from "yjs";
4
+ export type BlockNoteEditorOptions<BSpecs extends BlockSpecs, ISpecs extends InlineContentSpecs, SSpecs extends StyleSpecs> = {
5
+ blockSpecs: BSpecs;
6
+ styleSpecs: SSpecs;
7
+ inlineContentSpecs: ISpecs;
8
+ };
9
+ export declare class BlockNoteContext<BSchema extends BlockSchema = DefaultBlockSchema, ISchema extends InlineContentSchema = DefaultInlineContentSchema, SSchema extends StyleSchema = DefaultStyleSchema> {
10
+ readonly blockSchema: BSchema;
11
+ readonly inlineContentSchema: ISchema;
12
+ readonly styleSchema: SSchema;
13
+ readonly blockImplementations: BlockSpecs;
14
+ readonly inlineContentImplementations: InlineContentSpecs;
15
+ readonly styleImplementations: StyleSpecs;
16
+ readonly pmSchema: PMSchema;
17
+ static create<BSpecs extends BlockSpecs = typeof defaultBlockSpecs, ISpecs extends InlineContentSpecs = typeof defaultInlineContentSpecs, SSpecs extends StyleSpecs = typeof defaultStyleSpecs>(options?: Partial<BlockNoteEditorOptions<BSpecs, ISpecs, SSpecs>>): BlockNoteContext<BlockSchemaFromSpecs<BSpecs>, InlineContentSchemaFromSpecs<ISpecs>, StyleSchemaFromSpecs<SSpecs>>;
18
+ private constructor();
19
+ prosemirrorJSONToBlocks(json: any): Block<BSchema, InlineContentSchema, StyleSchema>[];
20
+ yDocToBlocks(ydoc: Y.Doc, xmlFragment?: string): Block<BSchema, InlineContentSchema, StyleSchema>[];
21
+ yXmlFragmentToBlocks(xmlFragment: Y.XmlFragment): Block<BSchema, InlineContentSchema, StyleSchema>[];
22
+ /**
23
+ * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list
24
+ * items are un-nested in the output HTML.
25
+ * @param blocks An array of blocks that should be serialized into HTML.
26
+ * @returns The blocks, serialized as an HTML string.
27
+ */
28
+ blocksToHTMLLossy(blocks: Block<BSchema, ISchema, SSchema>[]): Promise<string>;
29
+ /**
30
+ * Serializes blocks into an HTML string in the format that it would be rendered by the editor.
31
+ *
32
+ * Use this method if you want to server-side render HTML (for example, a blog post that has been edited in BlockNote)
33
+ * and serve it to users without loading the editor on the client (i.e.: displaying the blog post)
34
+ */
35
+ blocksToBlockNoteStyleHTML(blocks: Block<BSchema, ISchema, SSchema>[]): Promise<string>;
36
+ /**
37
+ * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and
38
+ * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote
39
+ * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.
40
+ * @param html The HTML string to parse blocks from.
41
+ * @returns The blocks parsed from the HTML string.
42
+ */
43
+ tryParseHTMLToBlocks(html: string): Promise<Block<BSchema, ISchema, SSchema>[]>;
44
+ /**
45
+ * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of
46
+ * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.
47
+ * @param blocks An array of blocks that should be serialized into Markdown.
48
+ * @returns The blocks, serialized as a Markdown string.
49
+ */
50
+ blocksToMarkdownLossy(blocks: Block<BSchema, ISchema, SSchema>[]): Promise<string>;
51
+ /**
52
+ * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on
53
+ * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it
54
+ * as text.
55
+ * @param markdown The Markdown string to parse blocks from.
56
+ * @returns The blocks parsed from the Markdown string.
57
+ */
58
+ tryParseMarkdownToBlocks(markdown: string): Promise<Block<BSchema, ISchema, SSchema>[]>;
59
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,137 @@
1
+ import { Block, BlockNoteEditor, BlockNoteEditorOptions, BlockSchema, DefaultBlockSchema, DefaultInlineContentSchema, DefaultStyleSchema, InlineContentSchema, PartialBlock, StyleSchema } from "@blocknote/core";
2
+ import { Node } from "@tiptap/pm/model";
3
+ import * as React from "react";
4
+ import type * as Y from "yjs";
5
+ /**
6
+ * Use the ServerBlockNoteEditor to interact with BlockNote documents in a server (nodejs) environment.
7
+ */
8
+ export declare class ServerBlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema, ISchema extends InlineContentSchema = DefaultInlineContentSchema, SSchema extends StyleSchema = DefaultStyleSchema> {
9
+ /**
10
+ * Internal BlockNoteEditor (not recommended to use directly, use the methods of this class instead)
11
+ */
12
+ readonly editor: BlockNoteEditor<BSchema, ISchema, SSchema>;
13
+ /**
14
+ * We currently use a JSDOM instance to mock document and window methods
15
+ *
16
+ * A possible improvement could be to make this:
17
+ * a) pluggable so other shims can be used as well
18
+ * b) obsolete, but for this all blocks should be React based and we need to remove all references to document / window
19
+ * from the core / react package. (and even then, it's likely some custom blocks would still use document / window methods)
20
+ */
21
+ private jsdom;
22
+ /**
23
+ * Calls a function with mocking window and document using JSDOM
24
+ *
25
+ * We could make this obsolete by passing in a document / window object to the render / serialize methods of Blocks
26
+ */
27
+ _withJSDOM<T>(fn: () => Promise<T>): Promise<T>;
28
+ static create<BSchema extends BlockSchema = DefaultBlockSchema, ISchema extends InlineContentSchema = DefaultInlineContentSchema, SSchema extends StyleSchema = DefaultStyleSchema>(options?: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>>): ServerBlockNoteEditor<BSchema, ISchema, SSchema>;
29
+ protected constructor(options: Partial<BlockNoteEditorOptions<any, any, any>>);
30
+ /** PROSEMIRROR / BLOCKNOTE conversions */
31
+ /**
32
+ * Turn Prosemirror JSON to BlockNote style JSON
33
+ * @param json Prosemirror JSON
34
+ * @returns BlockNote style JSON
35
+ */
36
+ _prosemirrorNodeToBlocks(pmNode: Node): Block<BSchema, InlineContentSchema, StyleSchema>[];
37
+ /**
38
+ * Turn Prosemirror JSON to BlockNote style JSON
39
+ * @param json Prosemirror JSON
40
+ * @returns BlockNote style JSON
41
+ */
42
+ _prosemirrorJSONToBlocks(json: any): Block<BSchema, InlineContentSchema, StyleSchema>[];
43
+ /**
44
+ * Turn BlockNote JSON to Prosemirror node / state
45
+ * @param blocks BlockNote blocks
46
+ * @returns Prosemirror root node
47
+ */
48
+ _blocksToProsemirrorNode(blocks: PartialBlock<BSchema, ISchema, SSchema>[]): Node;
49
+ /** YJS / BLOCKNOTE conversions */
50
+ /**
51
+ * Turn a Y.XmlFragment collaborative doc into a BlockNote document (BlockNote style JSON of all blocks)
52
+ * @returns BlockNote document (BlockNote style JSON of all blocks)
53
+ */
54
+ yXmlFragmentToBlocks(xmlFragment: Y.XmlFragment): Block<BSchema, InlineContentSchema, StyleSchema>[];
55
+ /**
56
+ * Convert blocks to a Y.XmlFragment
57
+ *
58
+ * This can be used when importing existing content to Y.Doc for the first time,
59
+ * note that this should not be used to rehydrate a Y.Doc from a database once
60
+ * collaboration has begun as all history will be lost
61
+ *
62
+ * @param blocks the blocks to convert
63
+ * @returns Y.XmlFragment
64
+ */
65
+ blocksToYXmlFragment(blocks: Block<BSchema, ISchema, SSchema>[], xmlFragment?: Y.XmlFragment): Y.XmlFragment;
66
+ /**
67
+ * Turn a Y.Doc collaborative doc into a BlockNote document (BlockNote style JSON of all blocks)
68
+ * @returns BlockNote document (BlockNote style JSON of all blocks)
69
+ */
70
+ yDocToBlocks(ydoc: Y.Doc, xmlFragment?: string): Block<BSchema, InlineContentSchema, StyleSchema>[];
71
+ /**
72
+ * This can be used when importing existing content to Y.Doc for the first time,
73
+ * note that this should not be used to rehydrate a Y.Doc from a database once
74
+ * collaboration has begun as all history will be lost
75
+ *
76
+ * @param blocks
77
+ */
78
+ blocksToYDoc(blocks: PartialBlock<BSchema, ISchema, SSchema>[], xmlFragment?: string): Y.Doc;
79
+ /** HTML / BLOCKNOTE conversions */
80
+ /**
81
+ * Exports blocks into a simplified HTML string. To better conform to HTML standards, children of blocks which aren't list
82
+ * items are un-nested in the output HTML.
83
+ *
84
+ * @param blocks An array of blocks that should be serialized into HTML.
85
+ * @returns The blocks, serialized as an HTML string.
86
+ */
87
+ blocksToHTMLLossy(blocks: PartialBlock<BSchema, ISchema, SSchema>[]): Promise<string>;
88
+ /**
89
+ * Serializes blocks into an HTML string in the format that would normally be rendered by the editor.
90
+ *
91
+ * Use this method if you want to server-side render HTML (for example, a blog post that has been edited in BlockNote)
92
+ * and serve it to users without loading the editor on the client (i.e.: displaying the blog post)
93
+ *
94
+ * @param blocks An array of blocks that should be serialized into HTML.
95
+ * @returns The blocks, serialized as an HTML string.
96
+ */
97
+ blocksToFullHTML(blocks: PartialBlock<BSchema, ISchema, SSchema>[]): Promise<string>;
98
+ /**
99
+ * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and
100
+ * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote
101
+ * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.
102
+ * @param html The HTML string to parse blocks from.
103
+ * @returns The blocks parsed from the HTML string.
104
+ */
105
+ tryParseHTMLToBlocks(html: string): Promise<Block<BSchema, ISchema, SSchema>[]>;
106
+ /** MARKDOWN / BLOCKNOTE conversions */
107
+ /**
108
+ * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of
109
+ * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.
110
+ * @param blocks An array of blocks that should be serialized into Markdown.
111
+ * @returns The blocks, serialized as a Markdown string.
112
+ */
113
+ blocksToMarkdownLossy(blocks: PartialBlock<BSchema, ISchema, SSchema>[]): Promise<string>;
114
+ /**
115
+ * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on
116
+ * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it
117
+ * as text.
118
+ * @param markdown The Markdown string to parse blocks from.
119
+ * @returns The blocks parsed from the Markdown string.
120
+ */
121
+ tryParseMarkdownToBlocks(markdown: string): Promise<Block<BSchema, ISchema, SSchema>[]>;
122
+ /**
123
+ * If you're using React Context in your blocks, you can use this method to wrap editor calls for importing / exporting / block manipulation
124
+ * with the React Context Provider.
125
+ *
126
+ * Example:
127
+ *
128
+ * ```tsx
129
+ const html = await editor.withReactContext(
130
+ ({ children }) => (
131
+ <YourContext.Provider value={true}>{children}</YourContext.Provider>
132
+ ),
133
+ async () => editor.blocksToFullHTML(blocks)
134
+ );
135
+ */
136
+ withReactContext<T>(comp: React.FC<any>, fn: () => Promise<T>): Promise<T>;
137
+ }
@@ -0,0 +1 @@
1
+ export {};