1
1
import { Editor , EditorOptions , Extension } from "@tiptap/core" ;
2
- import { Node } from "prosemirror-model" ;
2
+ import { Fragment , Node , Slice } from "prosemirror-model" ;
3
3
// import "./blocknote.css";
4
4
import { Editor as TiptapEditor } from "@tiptap/core/dist/packages/core/src/Editor" ;
5
5
import * as Y from "yjs" ;
@@ -24,7 +24,6 @@ import {
24
24
BlockSpecs ,
25
25
PartialBlock ,
26
26
} from "./extensions/Blocks/api/blocks/types" ;
27
- import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes" ;
28
27
import {
29
28
DefaultBlockSchema ,
30
29
DefaultInlineContentSchema ,
@@ -44,8 +43,14 @@ import {
44
43
import { getBlockInfoFromPos } from "./extensions/Blocks/helpers/getBlockInfoFromPos" ;
45
44
46
45
import "prosemirror-tables/style/tables.css" ;
46
+
47
+ import { createExternalHTMLExporter } from "./api/exporters/html/externalHTMLExporter" ;
48
+ import { blocksToMarkdown } from "./api/exporters/markdown/markdownExporter" ;
49
+ import { HTMLToBlocks } from "./api/parsers/html/parseHTML" ;
50
+ import { markdownToBlocks } from "./api/parsers/markdown/parseMarkdown" ;
47
51
import "./editor.css" ;
48
52
import { getBlockSchemaFromSpecs } from "./extensions/Blocks/api/blocks/internal" ;
53
+ import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes" ;
49
54
import { getInlineContentSchemaFromSpecs } from "./extensions/Blocks/api/inlineContent/internal" ;
50
55
import {
51
56
InlineContentSchema ,
@@ -409,6 +414,50 @@ export class BlockNoteEditor<
409
414
newOptions . domAttributes ?. editor ?. class || ""
410
415
) ,
411
416
} ,
417
+ transformPasted ( slice , view ) {
418
+ // helper function
419
+ function removeChild ( node : Fragment , n : number ) {
420
+ const children : any [ ] = [ ] ;
421
+ node . forEach ( ( child , _ , i ) => {
422
+ if ( i !== n ) {
423
+ children . push ( child ) ;
424
+ }
425
+ } ) ;
426
+ return Fragment . from ( children ) ;
427
+ }
428
+
429
+ // fix for https://github.com/ProseMirror/prosemirror/issues/1430#issuecomment-1822570821
430
+ let f = Fragment . from ( slice . content ) ;
431
+ for ( let i = 0 ; i < f . childCount ; i ++ ) {
432
+ if ( f . child ( i ) . type . spec . group === "blockContent" ) {
433
+ const content = [ f . child ( i ) ] ;
434
+ if ( i + 1 < f . childCount ) {
435
+ // when there is a blockGroup, it should be nested in the new blockcontainer
436
+ if ( f . child ( i + 1 ) . type . spec . group === "blockGroup" ) {
437
+ const nestedChild = f
438
+ . child ( i + 1 )
439
+ . child ( 0 )
440
+ . child ( 0 ) ;
441
+
442
+ if (
443
+ nestedChild . type . name === "bulletListItem" ||
444
+ nestedChild . type . name === "numberedListItem"
445
+ ) {
446
+ content . push ( f . child ( i + 1 ) ) ;
447
+ f = removeChild ( f , i + 1 ) ;
448
+ }
449
+ }
450
+ }
451
+ const container = view . state . schema . nodes . blockContainer . create (
452
+ undefined ,
453
+ content
454
+ ) ;
455
+ f = f . replaceChild ( i , container ) ;
456
+ }
457
+ }
458
+
459
+ return new Slice ( f , slice . openStart , slice . openEnd ) ;
460
+ } ,
412
461
} ,
413
462
} ;
414
463
@@ -942,47 +991,71 @@ export class BlockNoteEditor<
942
991
}
943
992
944
993
// TODO: Fix when implementing HTML/Markdown import & export
945
- // /**
946
- // * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list
947
- // * items are un-nested in the output HTML.
948
- // * @param blocks An array of blocks that should be serialized into HTML.
949
- // * @returns The blocks, serialized as an HTML string.
950
- // */
951
- // public async blocksToHTML(blocks: Block<BSchema>[]): Promise<string> {
952
- // return blocksToHTML(blocks, this._tiptapEditor.schema, this);
953
- // }
954
- //
955
- // /**
956
- // * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and
957
- // * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote
958
- // * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.
959
- // * @param html The HTML string to parse blocks from.
960
- // * @returns The blocks parsed from the HTML string.
961
- // */
962
- // public async HTMLToBlocks(html: string): Promise<Block<BSchema>[]> {
963
- // return HTMLToBlocks(html, this.schema, this._tiptapEditor.schema);
964
- // }
965
- //
966
- // /**
967
- // * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of
968
- // * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.
969
- // * @param blocks An array of blocks that should be serialized into Markdown.
970
- // * @returns The blocks, serialized as a Markdown string.
971
- // */
972
- // public async blocksToMarkdown(blocks: Block<BSchema>[]): Promise<string> {
973
- // return blocksToMarkdown(blocks, this._tiptapEditor.schema, this);
974
- // }
975
- //
976
- // /**
977
- // * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on
978
- // * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it
979
- // * as text.
980
- // * @param markdown The Markdown string to parse blocks from.
981
- // * @returns The blocks parsed from the Markdown string.
982
- // */
983
- // public async markdownToBlocks(markdown: string): Promise<Block<BSchema>[]> {
984
- // return markdownToBlocks(markdown, this.schema, this._tiptapEditor.schema);
985
- // }
994
+ /**
995
+ * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list
996
+ * items are un-nested in the output HTML.
997
+ * @param blocks An array of blocks that should be serialized into HTML.
998
+ * @returns The blocks, serialized as an HTML string.
999
+ */
1000
+ public async blocksToHTMLLossy (
1001
+ blocks = this . topLevelBlocks
1002
+ ) : Promise < string > {
1003
+ const exporter = createExternalHTMLExporter (
1004
+ this . _tiptapEditor . schema ,
1005
+ this
1006
+ ) ;
1007
+ return exporter . exportBlocks ( blocks ) ;
1008
+ }
1009
+
1010
+ /**
1011
+ * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and
1012
+ * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote
1013
+ * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.
1014
+ * @param html The HTML string to parse blocks from.
1015
+ * @returns The blocks parsed from the HTML string.
1016
+ */
1017
+ public async tryParseHTMLToBlocks (
1018
+ html : string
1019
+ ) : Promise < Block < BSchema , ISchema , SSchema > [ ] > {
1020
+ return HTMLToBlocks (
1021
+ html ,
1022
+ this . blockSchema ,
1023
+ this . inlineContentSchema ,
1024
+ this . styleSchema ,
1025
+ this . _tiptapEditor . schema
1026
+ ) ;
1027
+ }
1028
+
1029
+ /**
1030
+ * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of
1031
+ * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.
1032
+ * @param blocks An array of blocks that should be serialized into Markdown.
1033
+ * @returns The blocks, serialized as a Markdown string.
1034
+ */
1035
+ public async blocksToMarkdownLossy (
1036
+ blocks = this . topLevelBlocks
1037
+ ) : Promise < string > {
1038
+ return blocksToMarkdown ( blocks , this . _tiptapEditor . schema , this ) ;
1039
+ }
1040
+
1041
+ /**
1042
+ * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on
1043
+ * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it
1044
+ * as text.
1045
+ * @param markdown The Markdown string to parse blocks from.
1046
+ * @returns The blocks parsed from the Markdown string.
1047
+ */
1048
+ public async tryParseMarkdownToBlocks (
1049
+ markdown : string
1050
+ ) : Promise < Block < BSchema , ISchema , SSchema > [ ] > {
1051
+ return markdownToBlocks (
1052
+ markdown ,
1053
+ this . blockSchema ,
1054
+ this . inlineContentSchema ,
1055
+ this . styleSchema ,
1056
+ this . _tiptapEditor . schema
1057
+ ) ;
1058
+ }
986
1059
987
1060
/**
988
1061
* Updates the user info for the current user that's shown to other collaborators.
0 commit comments