@markdstage/markdstage 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/bin/markdstage.mjs +12 -0
- package/package.json +45 -0
- package/shared/README.md +1014 -0
- package/shared/THIRD-PARTY-NOTICES.md +19 -0
- package/shared/deck-state.mjs +105 -0
- package/shared/docs/custom-theme-authoring.md +208 -0
- package/shared/markdown-deck.mjs +220 -0
- package/shared/markdstage-guide.mjs +276 -0
- package/shared/presenter-window.mjs +17 -0
- package/shared/renderer/architecture-document.mjs +596 -0
- package/shared/renderer/architecture-edit.mjs +298 -0
- package/shared/renderer/architecture-editor.mjs +449 -0
- package/shared/renderer/architecture.mjs +4033 -0
- package/shared/renderer/import-path.mjs +11 -0
- package/shared/renderer/index.html +106 -0
- package/shared/renderer/renderer.js +2082 -0
- package/shared/renderer/slides.css +614 -0
- package/shared/renderer/speaker-notes.mjs +106 -0
- package/shared/renderer/theme.mjs +205 -0
- package/shared/runtime/browser.mjs +539 -0
- package/shared/runtime/custom-theme.mjs +135 -0
- package/shared/runtime/deck-session.mjs +188 -0
- package/shared/runtime/errors.mjs +17 -0
- package/shared/runtime/output-paths.mjs +159 -0
- package/shared/runtime/output.mjs +385 -0
- package/shared/runtime/presentation-server.mjs +505 -0
- package/shared/runtime/static-files.mjs +70 -0
- package/shared/schema/README.md +228 -0
- package/shared/schema/architecture-v1.schema.json +664 -0
- package/shared/schema/examples/web-app.architecture.json +119 -0
- package/shared/schema/theme-metadata-v1.schema.json +75 -0
- package/shared/schema/theme-v1.json +84 -0
- package/shared/scripts/architecture-assets.mjs +226 -0
- package/shared/scripts/asset-paths.mjs +92 -0
- package/shared/scripts/atomic-markdown-replace.mjs +46 -0
- package/shared/scripts/markdown-blocks.mjs +182 -0
- package/shared/scripts/markdown-files.mjs +63 -0
- package/shared/scripts/markdown-save-coordinator.mjs +18 -0
- package/shared/scripts/markdown-watcher.mjs +80 -0
- package/shared/scripts/theme-paths.mjs +108 -0
- package/shared/scripts/vendor-assets.mjs +132 -0
- package/shared/scripts/workspace-root.mjs +32 -0
- package/shared/vendor/highlight.LICENSE +29 -0
- package/shared/vendor/highlight.min.js +1244 -0
- package/shared/vendor/marked.min.js +6 -0
- package/shared/vendor/mermaid.min.js.part-0001 +268 -0
- package/shared/vendor/mermaid.min.js.part-0002 +304 -0
- package/shared/vendor/mermaid.min.js.part-0003 +324 -0
- package/shared/vendor/mermaid.min.js.part-0004 +374 -0
- package/shared/vendor/mermaid.min.js.part-0005 +564 -0
- package/shared/vendor/mermaid.min.js.part-0006 +1308 -0
- package/shared/vendor/mermaid.min.js.part-0007 +269 -0
- package/shared/vendor/purify.min.js +3 -0
- package/shared/vendor/vendor-assets.lock.json +60 -0
- package/src/cli.mjs +347 -0
- package/src/commands/capture.mjs +23 -0
- package/src/commands/export.mjs +18 -0
- package/src/commands/guide.mjs +23 -0
- package/src/commands/inspect.mjs +35 -0
- package/src/commands/present.mjs +91 -0
- package/src/commands/skill.mjs +114 -0
- package/src/commands/validate.mjs +79 -0
- package/src/deck.mjs +63 -0
- package/src/exit.mjs +58 -0
- package/src/runtime.mjs +77 -0
- package/src/skills.mjs +155 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
// PDF export, PNG capture, and fixed 16:9 layout inspection.
|
|
2
|
+
//
|
|
3
|
+
// The Canvas Extension and the MarkdStage CLI share this implementation so both
|
|
4
|
+
// produce byte-identical output. Callers provide a session object with:
|
|
5
|
+
// url, workspaceRoot, sourceName, slides, markdown, mode, index, theme,
|
|
6
|
+
// themeLocked, customThemeCss, customThemeMeta, exportJobs (Map), exporting,
|
|
7
|
+
// and an optional log(message, level) function.
|
|
8
|
+
|
|
9
|
+
import { mkdtemp, rename, rm, writeFile } from "node:fs/promises";
|
|
10
|
+
import { basename, extname, join } from "node:path";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { getOutputSnapshotSlides } from "../deck-state.mjs";
|
|
14
|
+
import { normalizeTheme } from "../renderer/theme.mjs";
|
|
15
|
+
import { MarkdStageError } from "./errors.mjs";
|
|
16
|
+
import {
|
|
17
|
+
findChromiumBrowser,
|
|
18
|
+
runCdpOutputBrowser,
|
|
19
|
+
runPdfBrowser,
|
|
20
|
+
verifyPdf,
|
|
21
|
+
verifyPng,
|
|
22
|
+
} from "./browser.mjs";
|
|
23
|
+
import {
|
|
24
|
+
prepareWorkspaceDirectory,
|
|
25
|
+
preparePdfOutputDirectory,
|
|
26
|
+
resolveCaptureOutputDirectory,
|
|
27
|
+
resolvePdfOutputPath,
|
|
28
|
+
} from "./output-paths.mjs";
|
|
29
|
+
|
|
30
|
+
export const MAX_CAPTURE_SLIDES = 10;
|
|
31
|
+
|
|
32
|
+
function logFor(inst, message, level = "info") {
|
|
33
|
+
try {
|
|
34
|
+
inst.log?.(message, level);
|
|
35
|
+
} catch (_) {
|
|
36
|
+
/* never let logging throw */
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function pageUrlFor(inst, params) {
|
|
41
|
+
const url = new URL(inst.url);
|
|
42
|
+
for (const [key, value] of Object.entries(params)) {
|
|
43
|
+
url.searchParams.set(key, String(value));
|
|
44
|
+
}
|
|
45
|
+
return url.href;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function createOutputSnapshot(inst, requestedTheme) {
|
|
49
|
+
const theme = requestedTheme === undefined ? inst.theme : normalizeTheme(requestedTheme);
|
|
50
|
+
return {
|
|
51
|
+
slides: getOutputSnapshotSlides(inst),
|
|
52
|
+
theme,
|
|
53
|
+
themeLocked: inst.themeLocked,
|
|
54
|
+
customThemeCss: inst.customThemeCss,
|
|
55
|
+
customThemeMeta: inst.customThemeMeta,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function createOutputJob(snapshot, kind) {
|
|
60
|
+
return {
|
|
61
|
+
slides: snapshot.slides,
|
|
62
|
+
theme: snapshot.theme,
|
|
63
|
+
themeLocked: snapshot.themeLocked,
|
|
64
|
+
customThemeCss: snapshot.customThemeCss,
|
|
65
|
+
customThemeMeta: snapshot.customThemeMeta,
|
|
66
|
+
kind,
|
|
67
|
+
status: "pending",
|
|
68
|
+
error: "",
|
|
69
|
+
layout: null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function runLayoutInspectionJob(inst, snapshot, browser) {
|
|
74
|
+
const token = randomUUID();
|
|
75
|
+
const profileDir = await mkdtemp(join(tmpdir(), "markdstage-inspect-"));
|
|
76
|
+
const job = createOutputJob(snapshot, "inspect");
|
|
77
|
+
inst.exportJobs.set(token, job);
|
|
78
|
+
try {
|
|
79
|
+
const pageUrl = pageUrlFor(inst, { print: 1, token });
|
|
80
|
+
await runCdpOutputBrowser(browser, pageUrl, profileDir, job, false);
|
|
81
|
+
if (!job.layout || !Array.isArray(job.layout.slides)) {
|
|
82
|
+
throw new Error("The layout renderer did not return diagnostics.");
|
|
83
|
+
}
|
|
84
|
+
return job.layout;
|
|
85
|
+
} finally {
|
|
86
|
+
inst.exportJobs.delete(token);
|
|
87
|
+
await rm(profileDir, { recursive: true, force: true }).catch(() => {});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function selectLayoutResults(layout, requestedIndex, includeFits) {
|
|
92
|
+
const selected =
|
|
93
|
+
requestedIndex === undefined
|
|
94
|
+
? layout.slides
|
|
95
|
+
: layout.slides.filter((slide) => slide.index === requestedIndex);
|
|
96
|
+
const issueCount = selected.filter((slide) => slide.pdfClipped).length;
|
|
97
|
+
return {
|
|
98
|
+
ok: true,
|
|
99
|
+
scope: requestedIndex === undefined ? "deck" : "slide",
|
|
100
|
+
...(requestedIndex === undefined
|
|
101
|
+
? {}
|
|
102
|
+
: { index: requestedIndex, page: requestedIndex + 1 }),
|
|
103
|
+
width: layout.width,
|
|
104
|
+
height: layout.height,
|
|
105
|
+
total: layout.total,
|
|
106
|
+
inspected: selected.length,
|
|
107
|
+
issueCount,
|
|
108
|
+
hasIssues: issueCount > 0,
|
|
109
|
+
slides: includeFits ? selected : selected.filter((slide) => slide.pdfClipped),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function inspectLayout(inst, requestedIndex, includeFits = false) {
|
|
114
|
+
if (inst.exporting) {
|
|
115
|
+
throw new MarkdStageError(
|
|
116
|
+
"output_in_progress",
|
|
117
|
+
"Another PDF, layout inspection, or PNG output job is already running for this canvas.",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const snapshot = createOutputSnapshot(inst);
|
|
121
|
+
if (!snapshot.slides.length) {
|
|
122
|
+
throw new MarkdStageError(
|
|
123
|
+
"no_deck",
|
|
124
|
+
"No slides are loaded. Load a deck before inspecting layout.",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if (
|
|
128
|
+
requestedIndex !== undefined &&
|
|
129
|
+
(!Number.isInteger(requestedIndex) ||
|
|
130
|
+
requestedIndex < 0 ||
|
|
131
|
+
requestedIndex >= snapshot.slides.length)
|
|
132
|
+
) {
|
|
133
|
+
throw new MarkdStageError(
|
|
134
|
+
"slide_out_of_range",
|
|
135
|
+
`Slide index must be between 0 and ${snapshot.slides.length - 1}.`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const browser = findChromiumBrowser();
|
|
139
|
+
if (!browser) {
|
|
140
|
+
throw new MarkdStageError(
|
|
141
|
+
"layout_browser_not_found",
|
|
142
|
+
"Layout inspection requires Microsoft Edge, Google Chrome, or Chromium.",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
inst.exporting = true;
|
|
147
|
+
try {
|
|
148
|
+
const layout = await runLayoutInspectionJob(inst, snapshot, browser);
|
|
149
|
+
return selectLayoutResults(layout, requestedIndex, Boolean(includeFits));
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (error instanceof MarkdStageError) throw error;
|
|
152
|
+
throw new MarkdStageError(
|
|
153
|
+
"layout_inspection_failed",
|
|
154
|
+
error?.message || "Layout inspection failed.",
|
|
155
|
+
);
|
|
156
|
+
} finally {
|
|
157
|
+
inst.exporting = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function normalizeCaptureIndexes(requestedIndexes, total) {
|
|
162
|
+
if (!Array.isArray(requestedIndexes) || requestedIndexes.length === 0) {
|
|
163
|
+
throw new MarkdStageError(
|
|
164
|
+
"invalid_input",
|
|
165
|
+
"indexes must be a non-empty array when provided.",
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const indexes = [...new Set(requestedIndexes)];
|
|
169
|
+
if (
|
|
170
|
+
indexes.some(
|
|
171
|
+
(index) => !Number.isInteger(index) || index < 0 || index >= total,
|
|
172
|
+
)
|
|
173
|
+
) {
|
|
174
|
+
throw new MarkdStageError(
|
|
175
|
+
"slide_out_of_range",
|
|
176
|
+
`Every slide index must be an integer between 0 and ${total - 1}.`,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
if (indexes.length > MAX_CAPTURE_SLIDES) {
|
|
180
|
+
throw new MarkdStageError(
|
|
181
|
+
"too_many_slides",
|
|
182
|
+
`At most ${MAX_CAPTURE_SLIDES} slides can be captured at once.`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
return indexes.sort((a, b) => a - b);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export async function captureSlides(
|
|
189
|
+
inst,
|
|
190
|
+
requestedIndexes,
|
|
191
|
+
requestedDirectory,
|
|
192
|
+
requestedTheme,
|
|
193
|
+
) {
|
|
194
|
+
if (inst.exporting) {
|
|
195
|
+
throw new MarkdStageError(
|
|
196
|
+
"output_in_progress",
|
|
197
|
+
"Another PDF, layout inspection, or PNG output job is already running for this canvas.",
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
const snapshot = createOutputSnapshot(inst, requestedTheme);
|
|
201
|
+
if (!snapshot.slides.length) {
|
|
202
|
+
throw new MarkdStageError(
|
|
203
|
+
"no_deck",
|
|
204
|
+
"No slides are loaded. Load a deck before capturing PNGs.",
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const browser = findChromiumBrowser();
|
|
208
|
+
if (!browser) {
|
|
209
|
+
throw new MarkdStageError(
|
|
210
|
+
"png_browser_not_found",
|
|
211
|
+
"PNG capture requires Microsoft Edge, Google Chrome, or Chromium.",
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
inst.exporting = true;
|
|
215
|
+
const pendingFiles = [];
|
|
216
|
+
try {
|
|
217
|
+
let inspection = null;
|
|
218
|
+
let indexes;
|
|
219
|
+
if (requestedIndexes === undefined) {
|
|
220
|
+
const layout = await runLayoutInspectionJob(inst, snapshot, browser);
|
|
221
|
+
inspection = selectLayoutResults(layout, undefined, false);
|
|
222
|
+
indexes = layout.slides
|
|
223
|
+
.filter((slide) => slide.pdfClipped)
|
|
224
|
+
.map((slide) => slide.index)
|
|
225
|
+
.slice(0, MAX_CAPTURE_SLIDES);
|
|
226
|
+
if (indexes.length === 0) {
|
|
227
|
+
return {
|
|
228
|
+
ok: true,
|
|
229
|
+
total: snapshot.slides.length,
|
|
230
|
+
captured: 0,
|
|
231
|
+
issueCount: 0,
|
|
232
|
+
message: "The PDF layout fits; no PNG capture is needed.",
|
|
233
|
+
files: [],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
indexes = normalizeCaptureIndexes(requestedIndexes, snapshot.slides.length);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const outputDirectory = resolveCaptureOutputDirectory(
|
|
241
|
+
inst.workspaceRoot,
|
|
242
|
+
inst.sourceName,
|
|
243
|
+
requestedDirectory,
|
|
244
|
+
);
|
|
245
|
+
await prepareWorkspaceDirectory(inst.workspaceRoot, outputDirectory, "PNG");
|
|
246
|
+
const pageDigits = Math.max(3, String(snapshot.slides.length).length);
|
|
247
|
+
const files = [];
|
|
248
|
+
|
|
249
|
+
for (const index of indexes) {
|
|
250
|
+
const token = randomUUID();
|
|
251
|
+
const pageNumber = String(index + 1).padStart(pageDigits, "0");
|
|
252
|
+
const outputPath = join(outputDirectory, `slide-${pageNumber}.png`);
|
|
253
|
+
const temporaryPath = join(outputDirectory, `.slide-${pageNumber}.${token}.tmp.png`);
|
|
254
|
+
const job = createOutputJob(snapshot, "capture");
|
|
255
|
+
const pageProfileDir = await mkdtemp(join(tmpdir(), "markdstage-capture-"));
|
|
256
|
+
inst.exportJobs.set(token, job);
|
|
257
|
+
let staged = false;
|
|
258
|
+
try {
|
|
259
|
+
const pageUrl = pageUrlFor(inst, { capture: 1, token, index });
|
|
260
|
+
const png = await runCdpOutputBrowser(browser, pageUrl, pageProfileDir, job, true);
|
|
261
|
+
if (!job.layout || !Array.isArray(job.layout.slides)) {
|
|
262
|
+
throw new Error("The PNG renderer did not return layout diagnostics.");
|
|
263
|
+
}
|
|
264
|
+
await writeFile(temporaryPath, png);
|
|
265
|
+
const image = await verifyPng(temporaryPath);
|
|
266
|
+
const diagnostic = job.layout.slides[0];
|
|
267
|
+
pendingFiles.push({ temporaryPath, outputPath });
|
|
268
|
+
staged = true;
|
|
269
|
+
files.push({
|
|
270
|
+
index,
|
|
271
|
+
page: index + 1,
|
|
272
|
+
path: outputPath,
|
|
273
|
+
...image,
|
|
274
|
+
layout: diagnostic,
|
|
275
|
+
});
|
|
276
|
+
} finally {
|
|
277
|
+
inst.exportJobs.delete(token);
|
|
278
|
+
if (!staged) await rm(temporaryPath, { force: true }).catch(() => {});
|
|
279
|
+
await rm(pageProfileDir, { recursive: true, force: true }).catch(() => {});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
for (const file of pendingFiles) {
|
|
284
|
+
await rm(file.outputPath, { force: true }).catch((error) => {
|
|
285
|
+
if (error?.code !== "ENOENT") throw error;
|
|
286
|
+
});
|
|
287
|
+
await rename(file.temporaryPath, file.outputPath);
|
|
288
|
+
file.temporaryPath = "";
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
ok: true,
|
|
293
|
+
directory: outputDirectory,
|
|
294
|
+
total: snapshot.slides.length,
|
|
295
|
+
captured: files.length,
|
|
296
|
+
issueCount:
|
|
297
|
+
inspection?.issueCount ?? files.filter((file) => file.layout?.pdfClipped).length,
|
|
298
|
+
theme: snapshot.theme,
|
|
299
|
+
files,
|
|
300
|
+
};
|
|
301
|
+
} catch (error) {
|
|
302
|
+
if (error instanceof MarkdStageError) throw error;
|
|
303
|
+
throw new MarkdStageError("png_capture_failed", error?.message || "PNG capture failed.");
|
|
304
|
+
} finally {
|
|
305
|
+
inst.exporting = false;
|
|
306
|
+
for (const file of pendingFiles) {
|
|
307
|
+
if (file.temporaryPath) {
|
|
308
|
+
await rm(file.temporaryPath, { force: true }).catch(() => {});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export async function exportPdf(inst, requestedPath, requestedTheme) {
|
|
315
|
+
if (inst.exporting) {
|
|
316
|
+
throw new MarkdStageError(
|
|
317
|
+
"export_in_progress",
|
|
318
|
+
"Another PDF, layout inspection, or PNG output job is already running for this canvas.",
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
inst.exporting = true;
|
|
322
|
+
let token = "";
|
|
323
|
+
let profileDir = "";
|
|
324
|
+
let temporaryOutputPath = "";
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
const snapshot = createOutputSnapshot(inst, requestedTheme);
|
|
328
|
+
if (!snapshot.slides.length) {
|
|
329
|
+
throw new MarkdStageError(
|
|
330
|
+
"no_deck",
|
|
331
|
+
"No slides are loaded. Load a deck before exporting PDF.",
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const browser = findChromiumBrowser();
|
|
336
|
+
if (!browser) {
|
|
337
|
+
throw new MarkdStageError(
|
|
338
|
+
"pdf_browser_not_found",
|
|
339
|
+
"PDF export requires Microsoft Edge, Google Chrome, or Chromium.",
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const outputPath = resolvePdfOutputPath(inst.workspaceRoot, requestedPath);
|
|
344
|
+
const outputParent = await preparePdfOutputDirectory(inst.workspaceRoot, outputPath);
|
|
345
|
+
token = randomUUID();
|
|
346
|
+
profileDir = await mkdtemp(join(tmpdir(), "markdstage-pdf-"));
|
|
347
|
+
const outputBase = basename(outputPath, extname(outputPath)) || "markdstage";
|
|
348
|
+
temporaryOutputPath = join(outputParent, `.${outputBase}.${token}.tmp.pdf`);
|
|
349
|
+
inst.exportJobs.set(token, createOutputJob(snapshot, "pdf"));
|
|
350
|
+
|
|
351
|
+
const pageUrl = pageUrlFor(inst, { print: 1, token });
|
|
352
|
+
await runPdfBrowser(browser, pageUrl, temporaryOutputPath, profileDir);
|
|
353
|
+
const exportJob = inst.exportJobs.get(token);
|
|
354
|
+
if (exportJob?.status !== "ready") {
|
|
355
|
+
throw new Error(
|
|
356
|
+
exportJob?.error || "The print renderer did not finish before the browser exited.",
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
const bytes = await verifyPdf(temporaryOutputPath);
|
|
360
|
+
await rename(temporaryOutputPath, outputPath);
|
|
361
|
+
temporaryOutputPath = "";
|
|
362
|
+
logFor(inst, `MarkdStage: exported ${snapshot.slides.length} slides to ${outputPath}`);
|
|
363
|
+
return {
|
|
364
|
+
ok: true,
|
|
365
|
+
path: outputPath,
|
|
366
|
+
total: snapshot.slides.length,
|
|
367
|
+
theme: snapshot.theme,
|
|
368
|
+
bytes,
|
|
369
|
+
};
|
|
370
|
+
} catch (error) {
|
|
371
|
+
if (error instanceof MarkdStageError) throw error;
|
|
372
|
+
throw new MarkdStageError("pdf_export_failed", error?.message || "PDF export failed.");
|
|
373
|
+
} finally {
|
|
374
|
+
if (token) {
|
|
375
|
+
inst.exportJobs.delete(token);
|
|
376
|
+
}
|
|
377
|
+
if (temporaryOutputPath) {
|
|
378
|
+
await rm(temporaryOutputPath, { force: true }).catch(() => {});
|
|
379
|
+
}
|
|
380
|
+
inst.exporting = false;
|
|
381
|
+
if (profileDir) {
|
|
382
|
+
await rm(profileDir, { recursive: true, force: true }).catch(() => {});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|