Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions coverage-thresholds.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
"lines": 96.71
},
"packages/web": {
"statements": 95.43,
"statements": 97.64864864864865,
"branches": 95.86,
"functions": 97.63,
"lines": 95.43
"functions": 97.93617021276596,
"lines": 97.62306368330465
},
"packages/vscode": {
"statements": 99,
Expand Down
10 changes: 7 additions & 3 deletions packages/vscode/src/export-pdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface ExportPdfDeps {
readonly readFile: (uri: vscode.Uri) => Promise<Uint8Array>;
readonly writeFile: (uri: vscode.Uri, data: Uint8Array) => Promise<void>;
readonly uriWithPath: (base: vscode.Uri, newPath: string) => vscode.Uri;
readonly isPrintToPdfRuntimeSupported?: () => boolean;
readonly createWebviewPanel: (
viewType: string,
title: string,
Expand Down Expand Up @@ -182,6 +183,8 @@ export function composeHtml(mdSource: string, opts: { theme: Theme; title: strin
// ---------------------------------------------------------------------------

const PRINT_LOAD_TIMEOUT_MS = 15_000;
const UNSUPPORTED_RUNTIME_MESSAGE =
"[PDF-PRINT] webview.printToPDF is not available in this VS Code runtime. Requires the Electron-based desktop VS Code.";

export async function renderHtmlToPdf(
html: string,
Expand Down Expand Up @@ -210,9 +213,7 @@ export async function renderHtmlToPdf(
await loaded;
const print = panel.webview.printToPDF;
if (typeof print !== "function") {
throw new Error(
"[PDF-PRINT] webview.printToPDF is not available in this VS Code runtime. Requires the Electron-based desktop VS Code."
);
throw new Error(UNSUPPORTED_RUNTIME_MESSAGE);
}
return await print({
marginsType: 0,
Expand Down Expand Up @@ -281,6 +282,9 @@ async function runExport(
): Promise<void> {
log.info("export-pdf invoked", { uri: sourceUri.toString() });
try {
if (deps.isPrintToPdfRuntimeSupported?.() === false) {
throw new Error(UNSUPPORTED_RUNTIME_MESSAGE);
}
const t0 = Date.now();
const src = await readMarkdown(sourceUri, deps);
const title = titleFromPath(sourceUri.path);
Expand Down
1 change: 1 addition & 0 deletions packages/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export const activate = (context: vscode.ExtensionContext) => {
readFile: (u) => Promise.resolve(vscode.workspace.fs.readFile(u)).then((b) => new Uint8Array(b)),
writeFile: (u, data) => Promise.resolve(vscode.workspace.fs.writeFile(u, data)),
uriWithPath: (base, newPath) => base.with({ path: newPath }),
isPrintToPdfRuntimeSupported: () => vscode.env.uiKind === vscode.UIKind.Desktop,
createWebviewPanel: (viewType, title, showOptions, opts) =>
vscode.window.createWebviewPanel(
viewType,
Expand Down
16 changes: 16 additions & 0 deletions packages/vscode/test/export-pdf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,22 @@ describe("exportPdf composer", () => {
expect(lines.some((l) => l.includes("export-pdf failed"))).toBe(true);
});

it("preflights unsupported runtimes before reading or composing the markdown", async () => {
const { deps, spies } = makeDeps({ noPrintToPdf: true });
const unsupportedDeps: ExportPdfDeps = {
...deps,
isPrintToPdfRuntimeSupported: () => false,
};

await exportPdf(SAMPLE_URI, { theme: "light" }, unsupportedDeps);

expect(spies.readFile).not.toHaveBeenCalled();
expect(spies.createWebviewPanel).not.toHaveBeenCalled();
expect(spies.writeFile).not.toHaveBeenCalled();
expect(spies.showErrorMessage).toHaveBeenCalledTimes(1);
expect((spies.showErrorMessage.mock.calls[0]?.[0] as string).toLowerCase()).toContain("desktop vs code");
});

it("serialises concurrent invocations on the same URI (per-uri lock)", async () => {
const { deps, spies } = makeDeps();
const a = exportPdf(SAMPLE_URI, { theme: "light" }, deps);
Expand Down
2 changes: 2 additions & 0 deletions packages/vscode/test/vscode-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { vi } from "vitest";

export const ViewColumn = { Beside: 2, Active: -1 } as const;
export const UIKind = { Desktop: 1, Web: 2 } as const;

const FAKE_PDF = new TextEncoder().encode("%PDF-1.7\n" + "x".repeat(2048) + "\n%%EOF\n");

Expand Down Expand Up @@ -124,5 +125,6 @@ export const Uri = {
};

export const env = {
uiKind: UIKind.Desktop,
openExternal: vi.fn((_u: unknown) => Promise.resolve(true)),
};
Loading