1
- import { DOMSerializer , Fragment , Node , Schema } from "prosemirror-model" ;
1
+ import { DOMSerializer , Schema } from "prosemirror-model" ;
2
2
3
3
import { PartialBlock } from "../../../blocks/defaultBlocks" ;
4
4
import type { BlockNoteEditor } from "../../../editor/BlockNoteEditor" ;
5
- import { BlockSchema , InlineContentSchema , StyleSchema } from "../../../schema" ;
5
+ import {
6
+ BlockSchema ,
7
+ InlineContent ,
8
+ InlineContentSchema ,
9
+ StyleSchema ,
10
+ } from "../../../schema" ;
6
11
import { esmDependencies } from "../../../util/esmDependencies" ;
7
- import { blockToNode } from "../../nodeConversions/nodeConversions" ;
8
12
import {
9
- serializeNodeInner ,
10
- serializeProseMirrorFragment ,
13
+ serializeBlocks ,
14
+ serializeInlineContent ,
11
15
} from "./util/sharedHTMLConversion" ;
12
16
import { simplifyBlocks } from "./util/simplifyBlocksRehypePlugin" ;
13
17
@@ -24,26 +28,6 @@ import { simplifyBlocks } from "./util/simplifyBlocksRehypePlugin";
24
28
// 3. While nesting for list items is preserved, other types of blocks nested
25
29
// inside a list are un-nested and a new list is created after them.
26
30
// 4. The HTML is wrapped in a single `div` element.
27
- //
28
- // The serializer has 2 main methods:
29
- // `exportBlocks`: Exports an array of blocks to HTML.
30
- // `exportFragment`: Exports a ProseMirror fragment to HTML. This is mostly
31
- // useful if you want to export a selection which may not start/end at the
32
- // start/end of a block.
33
- export interface ExternalHTMLExporter <
34
- BSchema extends BlockSchema ,
35
- I extends InlineContentSchema ,
36
- S extends StyleSchema
37
- > {
38
- exportBlocks : (
39
- blocks : PartialBlock < BSchema , I , S > [ ] ,
40
- options : { document ?: Document }
41
- ) => string ;
42
- exportProseMirrorFragment : (
43
- fragment : Fragment ,
44
- options : { document ?: Document ; simplifyBlocks ?: boolean }
45
- ) => string ;
46
- }
47
31
48
32
// Needs to be sync because it's used in drag handler event (SideMenuPlugin)
49
33
// Ideally, call `await initializeESMDependencies()` before calling this function
@@ -54,7 +38,7 @@ export const createExternalHTMLExporter = <
54
38
> (
55
39
schema : Schema ,
56
40
editor : BlockNoteEditor < BSchema , I , S >
57
- ) : ExternalHTMLExporter < BSchema , I , S > => {
41
+ ) => {
58
42
const deps = esmDependencies ;
59
43
60
44
if ( ! deps ) {
@@ -63,67 +47,63 @@ export const createExternalHTMLExporter = <
63
47
) ;
64
48
}
65
49
66
- // TODO: maybe cache this serializer (default prosemirror serializer is cached)?
67
- const serializer = new DOMSerializer (
68
- DOMSerializer . nodesFromSchema ( schema ) ,
69
- DOMSerializer . marksFromSchema ( schema )
70
- ) as DOMSerializer & {
71
- serializeNodeInner : (
72
- node : Node ,
73
- options : { document ?: Document }
74
- ) => HTMLElement ;
75
- exportProseMirrorFragment : (
76
- fragment : Fragment ,
77
- options : { document ?: Document ; simplifyBlocks ?: boolean }
78
- ) => string ;
50
+ const serializer = DOMSerializer . fromSchema ( schema ) ;
51
+
52
+ return {
79
53
exportBlocks : (
80
54
blocks : PartialBlock < BSchema , I , S > [ ] ,
81
55
options : { document ?: Document }
82
- ) => string ;
83
- } ;
56
+ ) => {
57
+ const html = serializeBlocks (
58
+ editor ,
59
+ blocks ,
60
+ serializer ,
61
+ true ,
62
+ options
63
+ ) . outerHTML ;
84
64
85
- serializer . serializeNodeInner = (
86
- node : Node ,
87
- options : { document ?: Document }
88
- ) => serializeNodeInner ( node , options , serializer , editor , true ) ;
65
+ // Possible improvement: now, we first use the serializeBlocks function
66
+ // which adds blockcontainer and blockgroup wrappers. We then pass the
67
+ // result to simplifyBlocks, which then cleans the wrappers.
68
+ //
69
+ // It might be easier if we create a version of serializeBlocks that
70
+ // doesn't add the wrappers in the first place, then we can get rid of
71
+ // the more complex simplifyBlocks plugin.
72
+ let externalHTML : any = deps . unified
73
+ . unified ( )
74
+ . use ( deps . rehypeParse . default , { fragment : true } ) ;
75
+ if ( ( options as any ) . simplifyBlocks !== false ) {
76
+ externalHTML = externalHTML . use ( simplifyBlocks , {
77
+ orderedListItemBlockTypes : new Set < string > ( [ "numberedListItem" ] ) ,
78
+ unorderedListItemBlockTypes : new Set < string > ( [
79
+ "bulletListItem" ,
80
+ "checkListItem" ,
81
+ ] ) ,
82
+ } ) ;
83
+ }
84
+ externalHTML = externalHTML
85
+ . use ( deps . rehypeStringify . default )
86
+ . processSync ( html ) ;
89
87
90
- // Like the `internalHTMLSerializer`, also uses `serializeProseMirrorFragment`
91
- // but additionally runs it through the `simplifyBlocks` rehype plugin to
92
- // convert the internal HTML to external.
93
- serializer . exportProseMirrorFragment = ( fragment , options ) => {
94
- let externalHTML : any = deps . unified
95
- . unified ( )
96
- . use ( deps . rehypeParse . default , { fragment : true } ) ;
97
- if ( options . simplifyBlocks !== false ) {
98
- externalHTML = externalHTML . use ( simplifyBlocks , {
99
- orderedListItemBlockTypes : new Set < string > ( [ "numberedListItem" ] ) ,
100
- unorderedListItemBlockTypes : new Set < string > ( [
101
- "bulletListItem" ,
102
- "checkListItem" ,
103
- ] ) ,
104
- } ) ;
105
- }
106
- externalHTML = externalHTML
107
- . use ( deps . rehypeStringify . default )
108
- . processSync ( serializeProseMirrorFragment ( fragment , serializer , options ) ) ;
88
+ return externalHTML . value as string ;
89
+ } ,
109
90
110
- return externalHTML . value as string ;
111
- } ;
91
+ exportInlineContent : (
92
+ inlineContent : InlineContent < I , S > [ ] ,
93
+ options : { simplifyBlocks : boolean ; document ?: Document }
94
+ ) => {
95
+ const domFragment = serializeInlineContent (
96
+ editor ,
97
+ inlineContent as any ,
98
+ serializer ,
99
+ true ,
100
+ options
101
+ ) ;
112
102
113
- serializer . exportBlocks = (
114
- blocks : PartialBlock < BSchema , I , S > [ ] ,
115
- options
116
- ) => {
117
- const nodes = blocks . map ( ( block ) =>
118
- blockToNode ( block , schema , editor . schema . styleSchema )
119
- ) ;
120
- const blockGroup = schema . nodes [ "blockGroup" ] . create ( null , nodes ) ;
103
+ const parent = document . createElement ( "div" ) ;
104
+ parent . append ( domFragment . cloneNode ( true ) ) ;
121
105
122
- return serializer . exportProseMirrorFragment (
123
- Fragment . from ( blockGroup ) ,
124
- options
125
- ) ;
106
+ return parent . innerHTML ;
107
+ } ,
126
108
} ;
127
-
128
- return serializer ;
129
109
} ;
0 commit comments