@@ -2,12 +2,6 @@ import { syntaxTree } from "@codemirror/language";
22import { EditorView , ViewPlugin , type ViewUpdate } from "@codemirror/view" ;
33import type { Client } from "../client.ts" ;
44
5- // We use turndown to convert HTML to Markdown
6- import TurndownService from "turndown" ;
7-
8- // With tables and task notation as well
9- // @ts -expect-error - No type definitions available for this package
10- import { tables , taskListItems } from "@joplin/turndown-plugin-gfm" ;
115import { lezerToParseTree } from "../markdown_parser/parse_tree.ts" ;
126import {
137 addParentPointers ,
@@ -21,17 +15,30 @@ import { localDateString } from "@silverbulletmd/silverbullet/lib/dates";
2115import type { UploadFile } from "@silverbulletmd/silverbullet/type/client" ;
2216import { isValidName , isValidPath } from "@silverbulletmd/silverbullet/lib/ref" ;
2317
24- const turndownService = new TurndownService ( {
25- hr : "---" ,
26- codeBlockStyle : "fenced" ,
27- headingStyle : "atx" ,
28- emDelimiter : "*" ,
29- bulletListMarker : "*" , // Duh!
30- strongDelimiter : "**" ,
31- linkStyle : "inlined" ,
32- } ) ;
33- turndownService . use ( taskListItems ) ;
34- turndownService . use ( tables ) ;
18+ // Dynamically load the turndown service (only used for clipboard pasete)
19+ let turndownService : any = null ;
20+ async function getTurndownService ( ) {
21+ if ( ! turndownService ) {
22+ const [ { default : TurndownService } , { tables, taskListItems } ] =
23+ await Promise . all ( [
24+ import ( "turndown" ) ,
25+ // @ts -expect-error - No type definitions available for this package
26+ import ( "@joplin/turndown-plugin-gfm" ) ,
27+ ] ) ;
28+ turndownService = new TurndownService ( {
29+ hr : "---" ,
30+ codeBlockStyle : "fenced" ,
31+ headingStyle : "atx" ,
32+ emDelimiter : "*" ,
33+ bulletListMarker : "*" , // Duh!
34+ strongDelimiter : "**" ,
35+ linkStyle : "inlined" ,
36+ } ) ;
37+ turndownService . use ( taskListItems ) ;
38+ turndownService . use ( tables ) ;
39+ }
40+ return turndownService ;
41+ }
3542
3643function striptHtmlComments ( s : string ) : string {
3744 return s . replace ( / < ! - - [ \s \S ] * ?- - > / g, "" ) ;
@@ -137,7 +144,7 @@ export function documentExtension(editor: Client) {
137144
138145 // Only do rich text paste if shift is NOT down
139146 if ( richText && ! shiftDown ) {
140- // Are we in a fencede code block?
147+ // Are we in a fenced code block?
141148 const editorText = editor . editorView . state . sliceDoc ( ) ;
142149 const tree = lezerToParseTree (
143150 editorText ,
@@ -161,23 +168,26 @@ export function documentExtension(editor: Client) {
161168 }
162169 }
163170
164- const markdown = striptHtmlComments (
165- turndownService . turndown ( richText ) ,
166- ) . trim ( ) ;
171+ // Prevent default immediately, then do async turndown conversion
172+ event . preventDefault ( ) ;
167173 const view = editor . editorView ;
168174 const selection = view . state . selection . main ;
169- view . dispatch ( {
170- changes : [
171- {
172- from : selection . from ,
173- to : selection . to ,
174- insert : markdown ,
175+ safeRun ( async ( ) => {
176+ const td = await getTurndownService ( ) ;
177+ const markdown = striptHtmlComments ( td . turndown ( richText ) ) . trim ( ) ;
178+ view . dispatch ( {
179+ changes : [
180+ {
181+ from : selection . from ,
182+ to : selection . to ,
183+ insert : markdown ,
184+ } ,
185+ ] ,
186+ selection : {
187+ anchor : selection . from + markdown . length ,
175188 } ,
176- ] ,
177- selection : {
178- anchor : selection . from + markdown . length ,
179- } ,
180- scrollIntoView : true ,
189+ scrollIntoView : true ,
190+ } ) ;
181191 } ) ;
182192 return true ;
183193 }
0 commit comments