Skip to content

Commit 8233b5b

Browse files
committed
Provide outputs to post processors when they are run
1 parent 34a7bab commit 8233b5b

File tree

6 files changed

+107
-35
lines changed

6 files changed

+107
-35
lines changed

src/command/render/latexmk/latexmk.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { OutputRecipe } from "../types.ts";
2424
import { generatePdf } from "./pdf.ts";
2525
import { LatexmkOptions } from "./types.ts";
2626
import { texToPdfOutputRecipe } from "../output-tex.ts";
27+
import { join } from "path/mod.ts";
28+
import { dirAndStem } from "../../../core/path.ts";
2729

2830
export function useQuartoLatexmk(
2931
format: Format,
@@ -57,7 +59,7 @@ export function quartoLatexmkOutputRecipe(
5759
// output dir
5860
const outputDir = format.render[kLatexOutputDir];
5961

60-
const pdfGenerator = (
62+
const generate = (
6163
input: string,
6264
format: Format,
6365
pandocOptions: PandocOptions,
@@ -87,13 +89,24 @@ export function quartoLatexmkOutputRecipe(
8789
return generatePdf(mkOptions);
8890
};
8991

92+
const computePath = (input: string, format: Format) => {
93+
const [cwd, stem] = dirAndStem(input);
94+
const mkOutputdir = format.render[kLatexOutputDir];
95+
return mkOutputdir
96+
? join(mkOutputdir, stem + ".pdf")
97+
: join(cwd, stem + ".pdf");
98+
};
99+
90100
return texToPdfOutputRecipe(
91101
input,
92102
finalOutput,
93103
options,
94104
format,
95105
"latex",
96-
pdfGenerator,
106+
{
107+
generate,
108+
computePath,
109+
},
97110
outputDir,
98111
);
99112
}

src/command/render/output-tex.ts

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ import { OutputRecipe } from "./types.ts";
2121
import { pdfEngine } from "../../config/pdf.ts";
2222
import { execProcess } from "../../core/process.ts";
2323

24-
export type PdfGenerator = (
25-
input: string,
26-
format: Format,
27-
pandocOptions: PandocOptions,
28-
) => Promise<string>;
24+
export interface PdfGenerator {
25+
generate: (
26+
input: string,
27+
format: Format,
28+
pandocOptions: PandocOptions,
29+
) => Promise<string>;
30+
computePath: (input: string, format: Format) => string;
31+
}
2932

3033
export function texToPdfOutputRecipe(
3134
input: string,
@@ -58,25 +61,14 @@ export function texToPdfOutputRecipe(
5861
// ouptut to the user's requested destination
5962
const complete = async (pandocOptions: PandocOptions) => {
6063
const input = join(inputDir, output);
61-
const pdfOutput = await pdfGenerator(input, format, pandocOptions);
64+
const pdfOutput = await pdfGenerator.generate(input, format, pandocOptions);
6265

6366
// keep tex if requested
6467
const compileTex = join(inputDir, output);
6568
if (!format.render[kKeepTex]) {
6669
Deno.removeSync(compileTex);
6770
}
6871

69-
const normalizePath = (input: string, output: string) => {
70-
if (isAbsolute(output)) {
71-
return output;
72-
} else {
73-
return relative(
74-
Deno.realPathSync(dirname(input)),
75-
Deno.realPathSync(output),
76-
);
77-
}
78-
};
79-
8072
// copy (or write for stdout) compiled pdf to final output location
8173
if (finalOutput) {
8274
if (finalOutput === kStdOut) {
@@ -111,6 +103,10 @@ export function texToPdfOutputRecipe(
111103
}
112104
};
113105

106+
const pdfOutput = finalOutput
107+
? finalOutput === kStdOut ? undefined : normalizePath(input, finalOutput)
108+
: normalizePath(input, pdfGenerator.computePath(input, format));
109+
114110
// tweak writer if it's pdf
115111
const to = format.pandoc.to === "pdf" ? pdfIntermediateTo : format.pandoc.to;
116112

@@ -127,6 +123,7 @@ export function texToPdfOutputRecipe(
127123
},
128124
},
129125
complete,
126+
finalOutput: pdfOutput,
130127
};
131128
}
132129

@@ -151,7 +148,12 @@ export function contextPdfOutputRecipe(
151148
options: RenderOptions,
152149
format: Format,
153150
): OutputRecipe {
154-
const pdfGenerator = async (
151+
const computePath = (input: string, _format: Format) => {
152+
const [dir, stem] = dirAndStem(input);
153+
return join(dir, stem + ".pdf");
154+
};
155+
156+
const generate = async (
155157
input: string,
156158
format: Format,
157159
pandocOptions: PandocOptions,
@@ -177,8 +179,7 @@ export function contextPdfOutputRecipe(
177179
// run context
178180
const result = await execProcess({ cmd });
179181
if (result.success) {
180-
const [dir, stem] = dirAndStem(input);
181-
return join(dir, stem + ".pdf");
182+
return computePath(input, format);
182183
} else {
183184
throw new Error();
184185
}
@@ -190,6 +191,20 @@ export function contextPdfOutputRecipe(
190191
options,
191192
format,
192193
"context",
193-
pdfGenerator,
194+
{
195+
generate,
196+
computePath,
197+
},
194198
);
195199
}
200+
201+
const normalizePath = (input: string, output: string) => {
202+
if (isAbsolute(output)) {
203+
return output;
204+
} else {
205+
return relative(
206+
dirname(input),
207+
output,
208+
);
209+
}
210+
};

src/command/render/render-files.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
PandocRenderer,
5151
RenderContext,
5252
RenderedFile,
53+
RenderedFormat,
5354
RenderExecuteOptions,
5455
RenderFile,
5556
RenderFilesResult,
@@ -88,6 +89,7 @@ import {
8889
} from "../../core/timing.ts";
8990
import { satisfies } from "semver/mod.ts";
9091
import { quartoConfig } from "../../core/quarto.ts";
92+
import { registerProjectType } from "../../project/types/project-types.ts";
9193

9294
export async function renderExecute(
9395
context: RenderContext,
@@ -351,6 +353,12 @@ export async function renderFiles(
351353
}
352354
executeResult.supporting.push(...results.supporting);
353355
};
356+
357+
const outputs: Array<{
358+
path: string;
359+
format: Format;
360+
}> = [];
361+
354362
for (const format of Object.keys(contexts)) {
355363
pushTiming("render-context");
356364
const context = ld.cloneDeep(contexts[format]) as RenderContext; // since we're going to mutate it...
@@ -388,6 +396,10 @@ export async function renderFiles(
388396

389397
// get output recipe
390398
const recipe = await outputRecipe(context);
399+
outputs.push({
400+
path: recipe.finalOutput || recipe.output,
401+
format: context.format,
402+
});
391403

392404
// determine execute options
393405
const executeOptions = mergeConfigs(
@@ -502,6 +514,7 @@ export async function renderFiles(
502514
popTiming();
503515
}
504516
}
517+
await pandocRenderer.onPostProcess(outputs);
505518
}
506519

507520
if (progress) {
@@ -531,22 +544,25 @@ function defaultPandocRenderer(
531544
_project?: ProjectContext,
532545
): PandocRenderer {
533546
const renderCompletions: PandocRenderCompletion[] = [];
547+
const renderedFiles: RenderedFile[] = [];
534548

535549
return {
536550
onBeforeExecute: (_format: Format) => ({}),
537-
538551
onRender: async (
539552
_format: string,
540553
executedFile: ExecutedFile,
541554
quiet: boolean,
542555
) => {
543556
renderCompletions.push(await renderPandoc(executedFile, quiet));
544557
},
545-
onComplete: async () => {
546-
const renderedFiles = [];
547-
for (const renderCompletion of renderCompletions) {
548-
renderedFiles.push(await renderCompletion.complete());
558+
onPostProcess: async (renderedFormats: RenderedFormat[]) => {
559+
let completion = renderCompletions.pop();
560+
while (completion) {
561+
renderedFiles.push(await completion.complete(renderedFormats));
562+
completion = renderCompletions.pop();
549563
}
564+
},
565+
onComplete: async () => {
550566
return {
551567
files: await Promise.resolve(renderedFiles),
552568
};

src/command/render/render.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
import { inputFilesDir } from "../../core/render.ts";
2121
import { pathWithForwardSlashes } from "../../core/path.ts";
2222

23-
import { FormatPandoc } from "../../config/types.ts";
23+
import { Format, FormatPandoc } from "../../config/types.ts";
2424
import {
2525
executionEngine,
2626
executionEngineKeepMd,
@@ -31,6 +31,7 @@ import {
3131
HtmlPostProcessResult,
3232
PandocInputTraits,
3333
PandocOptions,
34+
RenderedFormat,
3435
} from "./types.ts";
3536
import { runPandoc } from "./pandoc.ts";
3637
import { renderCleanup } from "./cleanup.ts";
@@ -54,7 +55,9 @@ import { replaceNotebookPlaceholders } from "../../core/jupyter/jupyter-embed.ts
5455
import { kIncludeAfterBody, kIncludeInHeader } from "../../config/constants.ts";
5556

5657
export interface PandocRenderCompletion {
57-
complete: () => Promise<RenderedFile>;
58+
complete: (
59+
outputs: RenderedFormat[],
60+
) => Promise<RenderedFile>;
5861
}
5962

6063
export async function renderPandoc(
@@ -164,7 +167,7 @@ export async function renderPandoc(
164167
}
165168

166169
return {
167-
complete: async () => {
170+
complete: async (renderedFormats: RenderedFormat[]) => {
168171
pushTiming("render-postprocessor");
169172
// run optional post-processor (e.g. to restore html-preserve regions)
170173
if (executeResult.postProcess) {

src/command/render/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,17 @@ export interface PandocRenderer {
125125
file: ExecutedFile,
126126
quiet: boolean,
127127
) => Promise<void>;
128+
onPostProcess: (
129+
renderedFormats: RenderedFormat[],
130+
) => Promise<void>;
128131
onComplete: (error?: boolean, quiet?: boolean) => Promise<RenderFilesResult>;
129132
}
130133

134+
export interface RenderedFormat {
135+
path: string;
136+
format: Format;
137+
}
138+
131139
export interface RenderFile {
132140
path: string;
133141
formats?: string[];
@@ -222,4 +230,7 @@ export interface OutputRecipe {
222230
// can optionally return an alternate output path. passed the actual
223231
// options used to run pandoc (for deducing e.g. pdf engine options)
224232
complete: (options: PandocOptions) => Promise<string | void>;
233+
234+
// The final output for the recipe (if different than the output itself)
235+
finalOutput?: string;
225236
}

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@ import {
3333
import { Format, Metadata } from "../../../config/types.ts";
3434
import { isHtmlOutput } from "../../../config/format.ts";
3535

36-
import { renderPandoc } from "../../../command/render/render.ts";
36+
import {
37+
PandocRenderCompletion,
38+
renderPandoc,
39+
} from "../../../command/render/render.ts";
3740

3841
import { renderContexts } from "../../../command/render/render-contexts.ts";
3942

4043
import {
4144
ExecutedFile,
4245
RenderContext,
4346
RenderedFile,
47+
RenderedFormat,
4448
RenderOptions,
4549
} from "../../../command/render/types.ts";
4650
import { outputRecipe } from "../../../command/render/output.ts";
@@ -96,6 +100,7 @@ export function bookPandocRenderer(
96100
// rendered files to return. some formats need to end up returning all of the individual
97101
// renderedFiles (e.g. html or asciidoc) and some formats will consolidate all of their
98102
// files into a single one (e.g. pdf or epub)
103+
const renderCompletions: PandocRenderCompletion[] = [];
99104
const renderedFiles: RenderedFile[] = [];
100105

101106
// accumulate executed files for formats that need deferred rendering
@@ -212,14 +217,22 @@ export function bookPandocRenderer(
212217

213218
// perform the render
214219
const renderCompletion = await renderPandoc(file, quiet);
215-
renderedFiles.push(await renderCompletion.complete());
216-
220+
renderCompletions.push(renderCompletion);
217221
// accumulate executed files for single file formats
218222
} else {
219223
executedFiles[format] = executedFiles[format] || [];
220224
executedFiles[format].push(file);
221225
}
222226
},
227+
onPostProcess: async (
228+
renderedFormats: RenderedFormat[],
229+
) => {
230+
let completion = renderCompletions.pop();
231+
while (completion) {
232+
renderedFiles.push(await completion.complete(renderedFormats));
233+
completion = renderCompletions.pop();
234+
}
235+
},
223236
onComplete: async (error?: boolean, quiet?: boolean) => {
224237
// if there was an error during execution then cleanup any
225238
// executed files we've accumulated and return no rendered files
@@ -302,7 +315,8 @@ async function renderSingleFileBook(
302315

303316
// do pandoc render
304317
const renderCompletion = await renderPandoc(executedFile, quiet);
305-
const renderedFile = await renderCompletion.complete();
318+
const renderedFormats: RenderedFormat[] = [];
319+
const renderedFile = await renderCompletion.complete(renderedFormats);
306320

307321
// cleanup step for each executed file
308322
files.forEach((file) => {

0 commit comments

Comments
 (0)