Skip to content

Commit 5dc8d51

Browse files
committed
Move post processing post pandoc rendering of all formats
1 parent d86012a commit 5dc8d51

File tree

3 files changed

+163
-146
lines changed

3 files changed

+163
-146
lines changed

src/command/render/render-files.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import { ojsExecuteResult } from "../../execute/ojs/compile.ts";
4242
import { ExecuteResult, MappedExecuteResult } from "../../execute/types.ts";
4343
import { kProjectLibDir, ProjectContext } from "../../project/types.ts";
4444
import { outputRecipe } from "./output.ts";
45-
import { renderPandoc } from "./render.ts";
45+
import { PandocRenderCompletion, renderPandoc } from "./render.ts";
4646
import { renderContexts } from "./render-contexts.ts";
4747
import { renderProgress } from "./render-info.ts";
4848
import {
@@ -530,7 +530,7 @@ function defaultPandocRenderer(
530530
_options: RenderOptions,
531531
_project?: ProjectContext,
532532
): PandocRenderer {
533-
const renderedFiles: RenderedFile[] = [];
533+
const renderCompletions: PandocRenderCompletion[] = [];
534534

535535
return {
536536
onBeforeExecute: (_format: Format) => ({}),
@@ -540,9 +540,13 @@ function defaultPandocRenderer(
540540
executedFile: ExecutedFile,
541541
quiet: boolean,
542542
) => {
543-
renderedFiles.push(await renderPandoc(executedFile, quiet));
543+
renderCompletions.push(await renderPandoc(executedFile, quiet));
544544
},
545545
onComplete: async () => {
546+
const renderedFiles = [];
547+
for (const renderCompletion of renderCompletions) {
548+
renderedFiles.push(await renderCompletion.complete());
549+
}
546550
return {
547551
files: await Promise.resolve(renderedFiles),
548552
};

src/command/render/render.ts

Lines changed: 152 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,14 @@ import { filesDirMediabagDir } from "./render-paths.ts";
5353
import { replaceNotebookPlaceholders } from "../../core/jupyter/jupyter-embed.ts";
5454
import { kIncludeAfterBody, kIncludeInHeader } from "../../config/constants.ts";
5555

56+
export interface PandocRenderCompletion {
57+
complete: () => Promise<RenderedFile>;
58+
}
59+
5660
export async function renderPandoc(
5761
file: ExecutedFile,
5862
quiet: boolean,
59-
): Promise<RenderedFile> {
63+
): Promise<PandocRenderCompletion> {
6064
// alias options
6165
const { context, recipe, executeResult, resourceFiles } = file;
6266

@@ -159,161 +163,168 @@ export async function renderPandoc(
159163
return Promise.reject();
160164
}
161165

162-
pushTiming("render-postprocessor");
163-
// run optional post-processor (e.g. to restore html-preserve regions)
164-
if (executeResult.postProcess) {
165-
await withTimingAsync("engine-postprocess", async () => {
166-
return await context.engine.postprocess({
167-
engine: context.engine,
168-
target: context.target,
169-
format,
170-
output: recipe.output,
171-
tempDir: context.options.services.temp.createDir(),
172-
projectDir: context.project?.dir,
173-
preserve: executeResult.preserve,
174-
quiet: context.options.flags?.quiet,
175-
});
176-
});
177-
}
166+
return {
167+
complete: async () => {
168+
pushTiming("render-postprocessor");
169+
// run optional post-processor (e.g. to restore html-preserve regions)
170+
if (executeResult.postProcess) {
171+
await withTimingAsync("engine-postprocess", async () => {
172+
return await context.engine.postprocess({
173+
engine: context.engine,
174+
target: context.target,
175+
format,
176+
output: recipe.output,
177+
tempDir: context.options.services.temp.createDir(),
178+
projectDir: context.project?.dir,
179+
preserve: executeResult.preserve,
180+
quiet: context.options.flags?.quiet,
181+
});
182+
});
183+
}
178184

179-
// run html postprocessors if we have them
180-
const canHtmlPostProcess = isHtmlFileOutput(format.pandoc);
181-
if (!canHtmlPostProcess && pandocResult.htmlPostprocessors.length > 0) {
182-
const postProcessorNames = pandocResult.htmlPostprocessors.map((p) =>
183-
p.name
184-
).join(", ");
185-
const msg =
186-
`Attempt to HTML post process non HTML output using: ${postProcessorNames}`;
187-
throw new Error(msg);
188-
}
189-
const htmlPostProcessors = canHtmlPostProcess
190-
? pandocResult.htmlPostprocessors
191-
: [];
192-
const htmlFinalizers = canHtmlPostProcess
193-
? pandocResult.htmlFinalizers || []
194-
: [];
195-
196-
const htmlPostProcessResult = await runHtmlPostprocessors(
197-
pandocResult.inputMetadata,
198-
pandocResult.inputTraits,
199-
pandocOptions,
200-
htmlPostProcessors,
201-
htmlFinalizers,
202-
);
185+
// run html postprocessors if we have them
186+
const canHtmlPostProcess = isHtmlFileOutput(format.pandoc);
187+
if (!canHtmlPostProcess && pandocResult.htmlPostprocessors.length > 0) {
188+
const postProcessorNames = pandocResult.htmlPostprocessors.map((p) =>
189+
p.name
190+
).join(", ");
191+
const msg =
192+
`Attempt to HTML post process non HTML output using: ${postProcessorNames}`;
193+
throw new Error(msg);
194+
}
195+
const htmlPostProcessors = canHtmlPostProcess
196+
? pandocResult.htmlPostprocessors
197+
: [];
198+
const htmlFinalizers = canHtmlPostProcess
199+
? pandocResult.htmlFinalizers || []
200+
: [];
201+
202+
const htmlPostProcessResult = await runHtmlPostprocessors(
203+
pandocResult.inputMetadata,
204+
pandocResult.inputTraits,
205+
pandocOptions,
206+
htmlPostProcessors,
207+
htmlFinalizers,
208+
);
203209

204-
// Compute the path to the output file
205-
const outputFile = isAbsolute(pandocOptions.output)
206-
? pandocOptions.output
207-
: join(dirname(pandocOptions.source), pandocOptions.output);
210+
// Compute the path to the output file
211+
const outputFile = isAbsolute(pandocOptions.output)
212+
? pandocOptions.output
213+
: join(dirname(pandocOptions.source), pandocOptions.output);
208214

209-
// run generic postprocessors
210-
if (pandocResult.postprocessors) {
211-
for (const postprocessor of pandocResult.postprocessors) {
212-
await postprocessor(outputFile);
213-
}
214-
}
215+
// run generic postprocessors
216+
if (pandocResult.postprocessors) {
217+
for (const postprocessor of pandocResult.postprocessors) {
218+
await postprocessor(outputFile);
219+
}
220+
}
215221

216-
let finalOutput: string;
217-
let selfContained: boolean;
222+
let finalOutput: string;
223+
let selfContained: boolean;
218224

219-
await withTimingAsync("postprocess-selfcontained", async () => {
220-
// ensure flags
221-
const flags = context.options.flags || {};
225+
await withTimingAsync("postprocess-selfcontained", async () => {
226+
// ensure flags
227+
const flags = context.options.flags || {};
222228

223-
// call complete handler (might e.g. run latexmk to complete the render)
224-
finalOutput = await recipe.complete(pandocOptions) || recipe.output;
229+
// call complete handler (might e.g. run latexmk to complete the render)
230+
finalOutput = await recipe.complete(pandocOptions) || recipe.output;
225231

226-
// determine whether this is self-contained output
227-
selfContained = isSelfContainedOutput(
228-
flags,
229-
format,
230-
finalOutput,
231-
);
232+
// determine whether this is self-contained output
233+
selfContained = isSelfContainedOutput(
234+
flags,
235+
format,
236+
finalOutput,
237+
);
232238

233-
// If this is self-contained, run pandoc to 'suck in' the dependencies
234-
// which may have been added in the post processor
235-
if (selfContained && isHtmlFileOutput(format.pandoc)) {
236-
await pandocIngestSelfContainedContent(outputFile);
237-
}
238-
});
239+
// If this is self-contained, run pandoc to 'suck in' the dependencies
240+
// which may have been added in the post processor
241+
if (selfContained && isHtmlFileOutput(format.pandoc)) {
242+
await pandocIngestSelfContainedContent(outputFile);
243+
}
244+
});
239245

240-
// compute the relative path to the files dir
241-
let filesDir: string | undefined = inputFilesDir(context.target.source);
242-
// undefine it if it doesn't exist
243-
filesDir = existsSync(join(dirname(context.target.source), filesDir))
244-
? filesDir
245-
: undefined;
246-
247-
// add any injected libs to supporting
248-
let supporting = filesDir ? executeResult.supporting : undefined;
249-
if (filesDir && isHtmlFileOutput(format.pandoc)) {
250-
const filesDirAbsolute = join(dirname(context.target.source), filesDir);
251-
if (
252-
existsSync(filesDirAbsolute) &&
253-
(!supporting || !supporting.includes(filesDirAbsolute))
254-
) {
255-
const filesLibs = join(dirname(context.target.source), context.libDir);
246+
// compute the relative path to the files dir
247+
let filesDir: string | undefined = inputFilesDir(context.target.source);
248+
// undefine it if it doesn't exist
249+
filesDir = existsSync(join(dirname(context.target.source), filesDir))
250+
? filesDir
251+
: undefined;
252+
253+
// add any injected libs to supporting
254+
let supporting = filesDir ? executeResult.supporting : undefined;
255+
if (filesDir && isHtmlFileOutput(format.pandoc)) {
256+
const filesDirAbsolute = join(dirname(context.target.source), filesDir);
257+
if (
258+
existsSync(filesDirAbsolute) &&
259+
(!supporting || !supporting.includes(filesDirAbsolute))
260+
) {
261+
const filesLibs = join(
262+
dirname(context.target.source),
263+
context.libDir,
264+
);
265+
if (
266+
existsSync(filesLibs) &&
267+
(!supporting || !supporting.includes(filesLibs))
268+
) {
269+
supporting = supporting || [];
270+
supporting.push(filesLibs);
271+
}
272+
}
273+
}
256274
if (
257-
existsSync(filesLibs) &&
258-
(!supporting || !supporting.includes(filesLibs))
275+
htmlPostProcessResult.supporting &&
276+
htmlPostProcessResult.supporting.length > 0
259277
) {
260278
supporting = supporting || [];
261-
supporting.push(filesLibs);
262-
}
263-
}
264-
}
265-
if (
266-
htmlPostProcessResult.supporting &&
267-
htmlPostProcessResult.supporting.length > 0
268-
) {
269-
supporting = supporting || [];
270-
supporting.push(...htmlPostProcessResult.supporting);
271-
}
272-
273-
withTiming("render-cleanup", () =>
274-
renderCleanup(
275-
context.target.input,
276-
finalOutput!,
277-
format,
278-
selfContained! ? supporting : undefined,
279-
executionEngineKeepMd(context.target.input),
280-
));
281-
282-
// if there is a project context then return paths relative to the project
283-
const projectPath = (path: string) => {
284-
if (context.project) {
285-
if (isAbsolute(path)) {
286-
return relative(
287-
Deno.realPathSync(context.project.dir),
288-
Deno.realPathSync(path),
289-
);
290-
} else {
291-
return relative(
292-
Deno.realPathSync(context.project.dir),
293-
Deno.realPathSync(join(dirname(context.target.source), path)),
294-
);
279+
supporting.push(...htmlPostProcessResult.supporting);
295280
}
296-
} else {
297-
return path;
298-
}
299-
};
300-
popTiming();
301281

302-
return {
303-
input: projectPath(context.target.source),
304-
markdown: executeResult.markdown,
305-
format,
306-
supporting: supporting
307-
? supporting.filter(existsSync).map((file: string) =>
308-
context.project ? relative(context.project.dir, file) : file
309-
)
310-
: undefined,
311-
file: projectPath(finalOutput!),
312-
resourceFiles: {
313-
globs: pandocResult.resources,
314-
files: resourceFiles.concat(htmlPostProcessResult.resources),
282+
withTiming("render-cleanup", () =>
283+
renderCleanup(
284+
context.target.input,
285+
finalOutput!,
286+
format,
287+
selfContained! ? supporting : undefined,
288+
executionEngineKeepMd(context.target.input),
289+
));
290+
291+
// if there is a project context then return paths relative to the project
292+
const projectPath = (path: string) => {
293+
if (context.project) {
294+
if (isAbsolute(path)) {
295+
return relative(
296+
Deno.realPathSync(context.project.dir),
297+
Deno.realPathSync(path),
298+
);
299+
} else {
300+
return relative(
301+
Deno.realPathSync(context.project.dir),
302+
Deno.realPathSync(join(dirname(context.target.source), path)),
303+
);
304+
}
305+
} else {
306+
return path;
307+
}
308+
};
309+
popTiming();
310+
311+
return {
312+
input: projectPath(context.target.source),
313+
markdown: executeResult.markdown,
314+
format,
315+
supporting: supporting
316+
? supporting.filter(existsSync).map((file: string) =>
317+
context.project ? relative(context.project.dir, file) : file
318+
)
319+
: undefined,
320+
file: projectPath(finalOutput!),
321+
resourceFiles: {
322+
globs: pandocResult.resources,
323+
files: resourceFiles.concat(htmlPostProcessResult.resources),
324+
},
325+
selfContained: selfContained!,
326+
};
315327
},
316-
selfContained: selfContained!,
317328
};
318329
}
319330

src/project/types/book/book-render.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ export function bookPandocRenderer(
211211
}
212212

213213
// perform the render
214-
renderedFiles.push(await renderPandoc(file, quiet));
214+
const renderCompletion = await renderPandoc(file, quiet);
215+
renderedFiles.push(await renderCompletion.complete());
215216

216217
// accumulate executed files for single file formats
217218
} else {
@@ -300,7 +301,8 @@ async function renderSingleFileBook(
300301
);
301302

302303
// do pandoc render
303-
const renderedFile = await renderPandoc(executedFile, quiet);
304+
const renderCompletion = await renderPandoc(executedFile, quiet);
305+
const renderedFile = await renderCompletion.complete();
304306

305307
// cleanup step for each executed file
306308
files.forEach((file) => {

0 commit comments

Comments
 (0)