From 5fcc3a3713e11a791d639aa2fb376f27ead304c3 Mon Sep 17 00:00:00 2001 From: abdushakoor12 Date: Wed, 29 Apr 2026 17:09:57 +0500 Subject: [PATCH 1/3] test(vscode): add pdf export runtime preflight regression --- packages/vscode/test/export-pdf.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/vscode/test/export-pdf.test.ts b/packages/vscode/test/export-pdf.test.ts index ea12703..3b7ff8e 100644 --- a/packages/vscode/test/export-pdf.test.ts +++ b/packages/vscode/test/export-pdf.test.ts @@ -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); From ac4e8a75b88c8668892328fb6f388b87b0109f06 Mon Sep 17 00:00:00 2001 From: abdushakoor12 Date: Wed, 29 Apr 2026 17:13:24 +0500 Subject: [PATCH 2/3] fix(vscode): preflight pdf export on unsupported runtimes --- packages/vscode/src/export-pdf.ts | 10 +++++++--- packages/vscode/src/extension.ts | 1 + packages/vscode/test/vscode-mock.ts | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/vscode/src/export-pdf.ts b/packages/vscode/src/export-pdf.ts index 9fa139d..89e0b90 100644 --- a/packages/vscode/src/export-pdf.ts +++ b/packages/vscode/src/export-pdf.ts @@ -21,6 +21,7 @@ export interface ExportPdfDeps { readonly readFile: (uri: vscode.Uri) => Promise; readonly writeFile: (uri: vscode.Uri, data: Uint8Array) => Promise; readonly uriWithPath: (base: vscode.Uri, newPath: string) => vscode.Uri; + readonly isPrintToPdfRuntimeSupported?: () => boolean; readonly createWebviewPanel: ( viewType: string, title: string, @@ -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, @@ -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, @@ -281,6 +282,9 @@ async function runExport( ): Promise { 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); diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index 8eb321c..604cc47 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -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, diff --git a/packages/vscode/test/vscode-mock.ts b/packages/vscode/test/vscode-mock.ts index 1ba9a38..a7bacf0 100644 --- a/packages/vscode/test/vscode-mock.ts +++ b/packages/vscode/test/vscode-mock.ts @@ -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"); @@ -124,5 +125,6 @@ export const Uri = { }; export const env = { + uiKind: UIKind.Desktop, openExternal: vi.fn((_u: unknown) => Promise.resolve(true)), }; From b5c2bbbfedcb564671669d8eb7748d910e3a452e Mon Sep 17 00:00:00 2001 From: abdushakoor12 Date: Wed, 29 Apr 2026 17:52:00 +0500 Subject: [PATCH 3/3] update coverage --- coverage-thresholds.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coverage-thresholds.json b/coverage-thresholds.json index cb9ddf0..6e1a5b6 100644 --- a/coverage-thresholds.json +++ b/coverage-thresholds.json @@ -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,