@@ -136,7 +136,8 @@ export default class MainController {
136136 logger ,
137137 ( ) => this . config ,
138138 extensionContext . extensionPath ,
139- this . isInExport
139+ this . isInExport ,
140+ this . onExportError
140141 )
141142 this . diagnostics = languages . createDiagnosticCollection ( 'vscode-revealjs' )
142143 this . configByKey = new Map ( configDesc . map ( ( d ) => [ d . label , d ] ) )
@@ -159,23 +160,41 @@ export default class MainController {
159160 }
160161 //#endregion
161162
162- // active export during 5 seconds
163- private exportTimeout : NodeJS . Timeout | null = null
164- public isInExport = ( ) => this . exportTimeout != null && this . exportTimeout != undefined
163+ private exportState : {
164+ resolve : ( path : string ) => void
165+ reject : ( error : Error ) => void
166+ path : string
167+ } | null = null
168+ public isInExport = ( ) => this . exportState !== null
169+
170+ private readonly onExportError = ( error : unknown ) => {
171+ if ( ! this . exportState ) return
172+
173+ const normalizedError = error instanceof Error ? error : new Error ( String ( error ) )
174+ this . exportState . reject ( new Error ( `HTML export failed: ${ normalizedError . message } ` ) )
175+ this . exportState = null
176+ }
165177
166178 public shouldOpenFilemanagerAfterHTMLExport = ( ) => this . currentContext ?. configuration . openFilemanagerAfterHTMLExport ?? false
167179
168180
169181 public exportAsync = async ( ) => {
170- if ( this . exportTimeout ) {
171- clearTimeout ( this . exportTimeout )
182+ if ( ! this . currentContext ) {
183+ throw new Error ( 'No active markdown context to export' )
184+ }
185+
186+ if ( this . exportState ) {
187+ this . exportState . reject ( new Error ( 'A previous HTML export was interrupted by a new export request' ) )
188+ this . exportState = null
172189 }
173- if ( this . currentContext ) { await jetpack . removeAsync ( this . currentContext . exportPath ) }
174190
175- const promise = new Promise < string > ( ( resolve ) => {
176- this . exportTimeout = setTimeout ( ( ) => resolve ( this . currentContext ?. exportPath ?? '' ) , 5000 )
191+ await jetpack . removeAsync ( this . currentContext . exportPath )
192+ const exportPath = this . currentContext . exportPath
193+
194+ const promise = new Promise < string > ( ( resolve , reject ) => {
195+ this . exportState = { resolve, reject, path : exportPath }
177196 } )
178- //await commands.executeCommand(SHOW_REVEALJS_IN_BROWSER)
197+
179198 this . webViewPane ? this . refreshWebViewPane ( ) : await commands . executeCommand ( SHOW_REVEALJS )
180199
181200 return promise
@@ -264,6 +283,14 @@ export default class MainController {
264283 if ( ! message || typeof message !== 'object' ) return
265284
266285 const command = 'command' in message ? message . command : undefined
286+ if ( command === 'exportComplete' ) {
287+ if ( this . exportState ) {
288+ this . exportState . resolve ( this . exportState . path )
289+ this . exportState = null
290+ }
291+ return
292+ }
293+
267294 if ( command !== 'slideChanged' ) return
268295
269296 const horizontal = 'horizontal' in message ? Number ( message . horizontal ) : Number . NaN
@@ -284,7 +311,7 @@ export default class MainController {
284311 if ( this . webViewPane && this . currentContext ) {
285312 this . startServer ( )
286313 this . webViewPane . title = this . currentContext . configuration . title
287- void this . webViewPane . update ( this . currentContext . uriWithPosition )
314+ void this . webViewPane . update ( this . currentContext . uriWithPosition , this . isInExport ( ) )
288315 }
289316 }
290317
0 commit comments