@@ -76,6 +76,7 @@ import {
7676} from "./freeze.ts" ;
7777import { isJupyterNotebook } from "../../core/jupyter/jupyter.ts" ;
7878import { MappedString } from "../../core/lib/text-types.ts" ;
79+ import { createNamedLifetime } from "../../core/lifetimes.ts" ;
7980
8081export async function renderExecute (
8182 context : RenderContext ,
@@ -282,7 +283,6 @@ export async function renderFiles(
282283 throw e ;
283284 }
284285 }
285-
286286 const mergeHandlerResults = (
287287 results : HandlerContextResults | undefined ,
288288 executeResult : MappedExecuteResult ,
@@ -312,125 +312,131 @@ export async function renderFiles(
312312 ] ;
313313 }
314314 } ;
315-
316315 for ( const format of Object . keys ( contexts ) ) {
317316 const context = ld . cloneDeep ( contexts [ format ] ) as RenderContext ; // since we're going to mutate it...
318317
319318 // Set the date locale for this render
320319 // Used for date formatting
321320 await setDateLocale ( context . format . metadata [ kLang ] as string ) ;
322321
323- // one time denoDom init for html compatible formats
324- if ( isHtmlCompatible ( context . format ) ) {
325- await initDenoDom ( ) ;
326- }
327-
328- // reset figure counter
329- resetFigureCounter ( ) ;
322+ const fileLifetime = createNamedLifetime ( "render-file" ) ;
323+ fileLifetime . attach ( {
324+ cleanup ( ) {
325+ resetFigureCounter ( ) ;
326+ } ,
327+ } ) ;
328+ try {
329+ // one time denoDom init for html compatible formats
330+ if ( isHtmlCompatible ( context . format ) ) {
331+ await initDenoDom ( ) ;
332+ }
330333
331- // get output recipe
332- const recipe = await outputRecipe ( context ) ;
334+ // get output recipe
335+ const recipe = await outputRecipe ( context ) ;
333336
334- // determine execute options
335- const executeOptions = mergeConfigs (
336- {
337- alwaysExecute : alwaysExecuteFiles ?. includes ( file . path ) ,
338- } ,
339- pandocRenderer . onBeforeExecute ( recipe . format ) ,
340- ) ;
337+ // determine execute options
338+ const executeOptions = mergeConfigs (
339+ {
340+ alwaysExecute : alwaysExecuteFiles ?. includes ( file . path ) ,
341+ } ,
342+ pandocRenderer . onBeforeExecute ( recipe . format ) ,
343+ ) ;
341344
342- const validate = context . format . metadata ?. [ "validate-yaml" ] ;
343- if ( validate !== false ) {
344- const validationResult = await validateDocument ( context ) ;
345- if ( validationResult . length ) {
346- throw new RenderInvalidYAMLError ( ) ;
345+ const validate = context . format . metadata ?. [ "validate-yaml" ] ;
346+ if ( validate !== false ) {
347+ const validationResult = await validateDocument ( context ) ;
348+ if ( validationResult . length ) {
349+ throw new RenderInvalidYAMLError ( ) ;
350+ }
347351 }
348- }
349352
350- // FIXME it should be possible to infer this directly now
351- // based on the information in the mapped strings.
352- //
353- // collect line numbers to facilitate runtime error reporting
354- const { ojsBlockLineNumbers } = annotateOjsLineNumbers ( context ) ;
355-
356- // execute
357- const baseExecuteResult = await renderExecute (
358- context ,
359- recipe . output ,
360- executeOptions ,
361- ) ;
353+ // FIXME it should be possible to infer this directly now
354+ // based on the information in the mapped strings.
355+ //
356+ // collect line numbers to facilitate runtime error reporting
357+ const { ojsBlockLineNumbers } = annotateOjsLineNumbers ( context ) ;
362358
363- // recover source map from diff and create a mappedExecuteResult
364- // for markdown processing pre-pandoc with mapped strings
365- let mappedMarkdown : MappedString ;
366-
367- if ( ! isJupyterNotebook ( context . target . source ) ) {
368- mappedMarkdown = mappedDiff (
369- context . target . markdown ,
370- baseExecuteResult . markdown ,
359+ // execute
360+ const baseExecuteResult = await renderExecute (
361+ context ,
362+ recipe . output ,
363+ executeOptions ,
371364 ) ;
372- } else {
373- mappedMarkdown = asMappedString ( baseExecuteResult . markdown ) ;
374- }
375365
376- const resourceFiles : string [ ] = [ ] ;
377- if ( baseExecuteResult . resourceFiles ) {
378- resourceFiles . push ( ...baseExecuteResult . resourceFiles ) ;
379- }
366+ // recover source map from diff and create a mappedExecuteResult
367+ // for markdown processing pre-pandoc with mapped strings
368+ let mappedMarkdown : MappedString ;
369+
370+ if ( ! isJupyterNotebook ( context . target . source ) ) {
371+ mappedMarkdown = mappedDiff (
372+ context . target . markdown ,
373+ baseExecuteResult . markdown ,
374+ ) ;
375+ } else {
376+ mappedMarkdown = asMappedString ( baseExecuteResult . markdown ) ;
377+ }
380378
381- const languageCellHandlerOptions : LanguageCellHandlerOptions = {
382- name : "" , // will be filled out by handleLanguageCells internally
383- temp : tempContext ,
384- format : recipe . format ,
385- markdown : mappedMarkdown ,
386- context,
387- stage : "post-engine" ,
388- } ;
389-
390- // handle language cells
391- const { markdown, results } = await handleLanguageCells (
392- languageCellHandlerOptions ,
393- ) ;
394- const mappedExecuteResult : MappedExecuteResult = {
395- ...baseExecuteResult ,
396- markdown,
397- } ;
398-
399- mergeHandlerResults (
400- context . target . preEngineExecuteResults ,
401- mappedExecuteResult ,
402- context ,
403- ) ;
404- mergeHandlerResults ( results , mappedExecuteResult , context ) ;
379+ const resourceFiles : string [ ] = [ ] ;
380+ if ( baseExecuteResult . resourceFiles ) {
381+ resourceFiles . push ( ...baseExecuteResult . resourceFiles ) ;
382+ }
405383
406- // process ojs
407- const { executeResult, resourceFiles : ojsResourceFiles } =
408- await ojsExecuteResult (
384+ const languageCellHandlerOptions : LanguageCellHandlerOptions = {
385+ name : "" , // will be filled out by handleLanguageCells internally
386+ temp : tempContext ,
387+ format : recipe . format ,
388+ markdown : mappedMarkdown ,
409389 context,
390+ stage : "post-engine" ,
391+ } ;
392+
393+ // handle language cells
394+ const { markdown, results } = await handleLanguageCells (
395+ languageCellHandlerOptions ,
396+ ) ;
397+ const mappedExecuteResult : MappedExecuteResult = {
398+ ...baseExecuteResult ,
399+ markdown,
400+ } ;
401+
402+ mergeHandlerResults (
403+ context . target . preEngineExecuteResults ,
410404 mappedExecuteResult ,
411- ojsBlockLineNumbers ,
405+ context ,
412406 ) ;
413- resourceFiles . push ( ...ojsResourceFiles ) ;
407+ mergeHandlerResults ( results , mappedExecuteResult , context ) ;
408+
409+ // process ojs
410+ const { executeResult, resourceFiles : ojsResourceFiles } =
411+ await ojsExecuteResult (
412+ context ,
413+ mappedExecuteResult ,
414+ ojsBlockLineNumbers ,
415+ ) ;
416+ resourceFiles . push ( ...ojsResourceFiles ) ;
417+
418+ // keep md if requested
419+ const keepMd = executionEngineKeepMd ( context . target . input ) ;
420+ if ( keepMd && context . format . execute [ kKeepMd ] ) {
421+ Deno . writeTextFileSync ( keepMd , executeResult . markdown . value ) ;
422+ }
414423
415- // keep md if requested
416- const keepMd = executionEngineKeepMd ( context . target . input ) ;
417- if ( keepMd && context . format . execute [ kKeepMd ] ) {
418- Deno . writeTextFileSync ( keepMd , executeResult . markdown . value ) ;
419- }
424+ // now get "unmapped" execute result back to send to pandoc
425+ const unmappedExecuteResult : ExecuteResult = {
426+ ... executeResult ,
427+ markdown : executeResult . markdown . value ,
428+ } ;
420429
421- // now get "unmapped" execute result back to send to pandoc
422- const unmappedExecuteResult : ExecuteResult = {
423- ...executeResult ,
424- markdown : executeResult . markdown . value ,
425- } ;
426-
427- // callback
428- await pandocRenderer . onRender ( format , {
429- context,
430- recipe,
431- executeResult : unmappedExecuteResult ,
432- resourceFiles,
433- } , pandocQuiet ) ;
430+ // callback
431+ await pandocRenderer . onRender ( format , {
432+ context,
433+ recipe,
434+ executeResult : unmappedExecuteResult ,
435+ resourceFiles,
436+ } , pandocQuiet ) ;
437+ } finally {
438+ fileLifetime . cleanup ( ) ;
439+ }
434440 }
435441 }
436442
0 commit comments