From 6cb365dd037d125f27280d29be3c04a711b94f76 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:04:09 +0000 Subject: [PATCH 1/7] fix: avoid empty PDF export for large markdown content Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- script.js | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/script.js b/script.js index ebafa41..1dbb81a 100644 --- a/script.js +++ b/script.js @@ -2586,13 +2586,38 @@ This is a fully client-side application. Your content never leaves your browser const margin = 15; const contentWidth = pageWidth - (margin * 2); + // Prevent oversized canvases for very large documents (can produce empty PDF output) + const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); + const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); + const desiredScale = PAGE_CONFIG.scale; + const MAX_CANVAS_DIMENSION = 32000; + const MAX_CANVAS_AREA = 250000000; // conservative browser-safe area + + const dimensionLimitedScale = Math.min( + desiredScale, + MAX_CANVAS_DIMENSION / renderWidth, + MAX_CANVAS_DIMENSION / renderHeight + ); + const areaLimitedScale = Math.min( + desiredScale, + Math.sqrt(MAX_CANVAS_AREA / (renderWidth * renderHeight)) + ); + const safeScale = Math.max(0.5, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale)); + + if (safeScale < desiredScale) { + console.warn( + `Reducing PDF render scale from ${desiredScale} to ${safeScale.toFixed(2)} ` + + `to avoid browser canvas limits for large content.` + ); + } + const canvas = await html2canvas(tempElement, { - scale: 2, + scale: safeScale, useCORS: true, allowTaint: true, logging: false, - windowWidth: 1000, - windowHeight: tempElement.scrollHeight + windowWidth: Math.ceil(renderWidth), + windowHeight: Math.ceil(renderHeight) }); const scaleFactor = canvas.width / contentWidth; From 3e501796544b0ad6c1509cba19283f607a601e36 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:05:11 +0000 Subject: [PATCH 2/7] docs: clarify PDF canvas safety limits and scale floor Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- desktop-app/resources/js/script.js | 31 +++++++++++++++++++++++++++--- script.js | 8 +++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index ebafa41..1dbb81a 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -2586,13 +2586,38 @@ This is a fully client-side application. Your content never leaves your browser const margin = 15; const contentWidth = pageWidth - (margin * 2); + // Prevent oversized canvases for very large documents (can produce empty PDF output) + const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); + const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); + const desiredScale = PAGE_CONFIG.scale; + const MAX_CANVAS_DIMENSION = 32000; + const MAX_CANVAS_AREA = 250000000; // conservative browser-safe area + + const dimensionLimitedScale = Math.min( + desiredScale, + MAX_CANVAS_DIMENSION / renderWidth, + MAX_CANVAS_DIMENSION / renderHeight + ); + const areaLimitedScale = Math.min( + desiredScale, + Math.sqrt(MAX_CANVAS_AREA / (renderWidth * renderHeight)) + ); + const safeScale = Math.max(0.5, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale)); + + if (safeScale < desiredScale) { + console.warn( + `Reducing PDF render scale from ${desiredScale} to ${safeScale.toFixed(2)} ` + + `to avoid browser canvas limits for large content.` + ); + } + const canvas = await html2canvas(tempElement, { - scale: 2, + scale: safeScale, useCORS: true, allowTaint: true, logging: false, - windowWidth: 1000, - windowHeight: tempElement.scrollHeight + windowWidth: Math.ceil(renderWidth), + windowHeight: Math.ceil(renderHeight) }); const scaleFactor = canvas.width / contentWidth; diff --git a/script.js b/script.js index 1dbb81a..8b79220 100644 --- a/script.js +++ b/script.js @@ -2590,8 +2590,12 @@ This is a fully client-side application. Your content never leaves your browser const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; + // Browser canvas implementations commonly fail/blank around 32,767 px in either dimension. + // Keep a margin under that practical limit for cross-browser stability. const MAX_CANVAS_DIMENSION = 32000; - const MAX_CANVAS_AREA = 250000000; // conservative browser-safe area + // Very large total pixel areas can also fail on some engines even below dimension limits. + // 250M px is a conservative cap to avoid blank exports on large markdown documents. + const MAX_CANVAS_AREA = 250000000; const dimensionLimitedScale = Math.min( desiredScale, @@ -2602,6 +2606,8 @@ This is a fully client-side application. Your content never leaves your browser desiredScale, Math.sqrt(MAX_CANVAS_AREA / (renderWidth * renderHeight)) ); + // Keep readability by not scaling below 50%; this preserves text legibility + // while still preventing empty exports caused by oversized canvas allocations. const safeScale = Math.max(0.5, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale)); if (safeScale < desiredScale) { From aa549c907920085f55bfe202787f74f3a3a7523f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:06:36 +0000 Subject: [PATCH 3/7] refactor: extract PDF canvas safety constants Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- desktop-app/resources/js/script.js | 22 +++++++++++++++------- script.js | 28 +++++++++++++++------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 1dbb81a..4f52f46 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -2023,6 +2023,14 @@ This is a fully client-side application. Your content never leaves your browser windowWidth: 1000, // html2canvas config scale: 2 // html2canvas scale factor }; + // Browser canvas implementations commonly fail/blank around 32,767 px in either dimension. + // Keep a margin under that practical limit for cross-browser stability. + const MAX_PDF_CANVAS_DIMENSION = 32000; + // Very large total pixel areas can also fail on some engines even below dimension limits. + // 250M px is a conservative cap to avoid blank exports on large markdown documents. + const MAX_PDF_CANVAS_AREA = 250000000; + // Keep readability by not scaling below 50% for PDF capture. + const MIN_READABLE_PDF_SCALE = 0.5; /** * Task 1: Identifies all graphic elements that may need page-break handling @@ -2590,19 +2598,19 @@ This is a fully client-side application. Your content never leaves your browser const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; - const MAX_CANVAS_DIMENSION = 32000; - const MAX_CANVAS_AREA = 250000000; // conservative browser-safe area - const dimensionLimitedScale = Math.min( desiredScale, - MAX_CANVAS_DIMENSION / renderWidth, - MAX_CANVAS_DIMENSION / renderHeight + MAX_PDF_CANVAS_DIMENSION / renderWidth, + MAX_PDF_CANVAS_DIMENSION / renderHeight ); const areaLimitedScale = Math.min( desiredScale, - Math.sqrt(MAX_CANVAS_AREA / (renderWidth * renderHeight)) + Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)) + ); + const safeScale = Math.max( + MIN_READABLE_PDF_SCALE, + Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) ); - const safeScale = Math.max(0.5, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale)); if (safeScale < desiredScale) { console.warn( diff --git a/script.js b/script.js index 8b79220..4f52f46 100644 --- a/script.js +++ b/script.js @@ -2023,6 +2023,14 @@ This is a fully client-side application. Your content never leaves your browser windowWidth: 1000, // html2canvas config scale: 2 // html2canvas scale factor }; + // Browser canvas implementations commonly fail/blank around 32,767 px in either dimension. + // Keep a margin under that practical limit for cross-browser stability. + const MAX_PDF_CANVAS_DIMENSION = 32000; + // Very large total pixel areas can also fail on some engines even below dimension limits. + // 250M px is a conservative cap to avoid blank exports on large markdown documents. + const MAX_PDF_CANVAS_AREA = 250000000; + // Keep readability by not scaling below 50% for PDF capture. + const MIN_READABLE_PDF_SCALE = 0.5; /** * Task 1: Identifies all graphic elements that may need page-break handling @@ -2590,25 +2598,19 @@ This is a fully client-side application. Your content never leaves your browser const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; - // Browser canvas implementations commonly fail/blank around 32,767 px in either dimension. - // Keep a margin under that practical limit for cross-browser stability. - const MAX_CANVAS_DIMENSION = 32000; - // Very large total pixel areas can also fail on some engines even below dimension limits. - // 250M px is a conservative cap to avoid blank exports on large markdown documents. - const MAX_CANVAS_AREA = 250000000; - const dimensionLimitedScale = Math.min( desiredScale, - MAX_CANVAS_DIMENSION / renderWidth, - MAX_CANVAS_DIMENSION / renderHeight + MAX_PDF_CANVAS_DIMENSION / renderWidth, + MAX_PDF_CANVAS_DIMENSION / renderHeight ); const areaLimitedScale = Math.min( desiredScale, - Math.sqrt(MAX_CANVAS_AREA / (renderWidth * renderHeight)) + Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)) + ); + const safeScale = Math.max( + MIN_READABLE_PDF_SCALE, + Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) ); - // Keep readability by not scaling below 50%; this preserves text legibility - // while still preventing empty exports caused by oversized canvas allocations. - const safeScale = Math.max(0.5, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale)); if (safeScale < desiredScale) { console.warn( From 65098e23d008b30cfc1dcc741f9ecc0d38623281 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:07:34 +0000 Subject: [PATCH 4/7] refactor: simplify PDF safe-scale calculation Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- script.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/script.js b/script.js index 4f52f46..9d57a9e 100644 --- a/script.js +++ b/script.js @@ -2599,14 +2599,10 @@ This is a fully client-side application. Your content never leaves your browser const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - desiredScale, MAX_PDF_CANVAS_DIMENSION / renderWidth, MAX_PDF_CANVAS_DIMENSION / renderHeight ); - const areaLimitedScale = Math.min( - desiredScale, - Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)) - ); + const areaLimitedScale = Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)); const safeScale = Math.max( MIN_READABLE_PDF_SCALE, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) From 2c14ea279a653eda4f3efe096012523442718df4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:08:43 +0000 Subject: [PATCH 5/7] chore: finalize PDF export scale safety cleanup Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- desktop-app/resources/js/script.js | 6 +----- script.js | 17 ++++++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 4f52f46..9d57a9e 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -2599,14 +2599,10 @@ This is a fully client-side application. Your content never leaves your browser const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - desiredScale, MAX_PDF_CANVAS_DIMENSION / renderWidth, MAX_PDF_CANVAS_DIMENSION / renderHeight ); - const areaLimitedScale = Math.min( - desiredScale, - Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)) - ); + const areaLimitedScale = Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)); const safeScale = Math.max( MIN_READABLE_PDF_SCALE, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) diff --git a/script.js b/script.js index 9d57a9e..2ce6ecc 100644 --- a/script.js +++ b/script.js @@ -2595,14 +2595,17 @@ This is a fully client-side application. Your content never leaves your browser const contentWidth = pageWidth - (margin * 2); // Prevent oversized canvases for very large documents (can produce empty PDF output) - const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); - const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); + const elementWidth = Math.max(tempElement.offsetWidth || 0, 1); + const elementHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - MAX_PDF_CANVAS_DIMENSION / renderWidth, - MAX_PDF_CANVAS_DIMENSION / renderHeight + MAX_PDF_CANVAS_DIMENSION / elementWidth, + MAX_PDF_CANVAS_DIMENSION / elementHeight ); - const areaLimitedScale = Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)); + const elementArea = elementWidth * elementHeight; + const areaLimitedScale = Number.isFinite(elementArea) && elementArea > 0 + ? Math.sqrt(MAX_PDF_CANVAS_AREA / elementArea) + : 1; const safeScale = Math.max( MIN_READABLE_PDF_SCALE, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) @@ -2620,8 +2623,8 @@ This is a fully client-side application. Your content never leaves your browser useCORS: true, allowTaint: true, logging: false, - windowWidth: Math.ceil(renderWidth), - windowHeight: Math.ceil(renderHeight) + windowWidth: Math.ceil(elementWidth), + windowHeight: Math.ceil(elementHeight) }); const scaleFactor = canvas.width / contentWidth; From fbfca4dfc859377b54a2f162bfa91286f8a5e3a7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:09:36 +0000 Subject: [PATCH 6/7] chore: polish PDF scale variable naming and fallback docs Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- desktop-app/resources/js/script.js | 17 ++++++++++------- script.js | 15 ++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 9d57a9e..2ce6ecc 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -2595,14 +2595,17 @@ This is a fully client-side application. Your content never leaves your browser const contentWidth = pageWidth - (margin * 2); // Prevent oversized canvases for very large documents (can produce empty PDF output) - const renderWidth = Math.max(tempElement.offsetWidth || 0, 1); - const renderHeight = Math.max(tempElement.scrollHeight || 0, 1); + const elementWidth = Math.max(tempElement.offsetWidth || 0, 1); + const elementHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - MAX_PDF_CANVAS_DIMENSION / renderWidth, - MAX_PDF_CANVAS_DIMENSION / renderHeight + MAX_PDF_CANVAS_DIMENSION / elementWidth, + MAX_PDF_CANVAS_DIMENSION / elementHeight ); - const areaLimitedScale = Math.sqrt(MAX_PDF_CANVAS_AREA / (renderWidth * renderHeight)); + const elementArea = elementWidth * elementHeight; + const areaLimitedScale = Number.isFinite(elementArea) && elementArea > 0 + ? Math.sqrt(MAX_PDF_CANVAS_AREA / elementArea) + : 1; const safeScale = Math.max( MIN_READABLE_PDF_SCALE, Math.min(desiredScale, dimensionLimitedScale, areaLimitedScale) @@ -2620,8 +2623,8 @@ This is a fully client-side application. Your content never leaves your browser useCORS: true, allowTaint: true, logging: false, - windowWidth: Math.ceil(renderWidth), - windowHeight: Math.ceil(renderHeight) + windowWidth: Math.ceil(elementWidth), + windowHeight: Math.ceil(elementHeight) }); const scaleFactor = canvas.width / contentWidth; diff --git a/script.js b/script.js index 2ce6ecc..e4a5c21 100644 --- a/script.js +++ b/script.js @@ -2595,16 +2595,17 @@ This is a fully client-side application. Your content never leaves your browser const contentWidth = pageWidth - (margin * 2); // Prevent oversized canvases for very large documents (can produce empty PDF output) - const elementWidth = Math.max(tempElement.offsetWidth || 0, 1); - const elementHeight = Math.max(tempElement.scrollHeight || 0, 1); + const actualElementWidth = Math.max(tempElement.offsetWidth || 0, 1); + const actualElementHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - MAX_PDF_CANVAS_DIMENSION / elementWidth, - MAX_PDF_CANVAS_DIMENSION / elementHeight + MAX_PDF_CANVAS_DIMENSION / actualElementWidth, + MAX_PDF_CANVAS_DIMENSION / actualElementHeight ); - const elementArea = elementWidth * elementHeight; + const elementArea = actualElementWidth * actualElementHeight; const areaLimitedScale = Number.isFinite(elementArea) && elementArea > 0 ? Math.sqrt(MAX_PDF_CANVAS_AREA / elementArea) + // Fallback to 1 (no extra area-based reduction) when area is invalid. : 1; const safeScale = Math.max( MIN_READABLE_PDF_SCALE, @@ -2623,8 +2624,8 @@ This is a fully client-side application. Your content never leaves your browser useCORS: true, allowTaint: true, logging: false, - windowWidth: Math.ceil(elementWidth), - windowHeight: Math.ceil(elementHeight) + windowWidth: Math.ceil(actualElementWidth), + windowHeight: Math.ceil(actualElementHeight) }); const scaleFactor = canvas.width / contentWidth; From 4ff6fcfe111e98c4825981452c3e20490a8950f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:10:14 +0000 Subject: [PATCH 7/7] Prevent blank PDF exports for large Markdown documents by bounding html2canvas render scale Agent-Logs-Url: https://github.com/ThisIs-Developer/Markdown-Viewer/sessions/d80d4d3a-e671-48a7-8411-d69ce79349a8 Co-authored-by: ThisIs-Developer <109382325+ThisIs-Developer@users.noreply.github.com> --- desktop-app/resources/js/script.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 2ce6ecc..e4a5c21 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -2595,16 +2595,17 @@ This is a fully client-side application. Your content never leaves your browser const contentWidth = pageWidth - (margin * 2); // Prevent oversized canvases for very large documents (can produce empty PDF output) - const elementWidth = Math.max(tempElement.offsetWidth || 0, 1); - const elementHeight = Math.max(tempElement.scrollHeight || 0, 1); + const actualElementWidth = Math.max(tempElement.offsetWidth || 0, 1); + const actualElementHeight = Math.max(tempElement.scrollHeight || 0, 1); const desiredScale = PAGE_CONFIG.scale; const dimensionLimitedScale = Math.min( - MAX_PDF_CANVAS_DIMENSION / elementWidth, - MAX_PDF_CANVAS_DIMENSION / elementHeight + MAX_PDF_CANVAS_DIMENSION / actualElementWidth, + MAX_PDF_CANVAS_DIMENSION / actualElementHeight ); - const elementArea = elementWidth * elementHeight; + const elementArea = actualElementWidth * actualElementHeight; const areaLimitedScale = Number.isFinite(elementArea) && elementArea > 0 ? Math.sqrt(MAX_PDF_CANVAS_AREA / elementArea) + // Fallback to 1 (no extra area-based reduction) when area is invalid. : 1; const safeScale = Math.max( MIN_READABLE_PDF_SCALE, @@ -2623,8 +2624,8 @@ This is a fully client-side application. Your content never leaves your browser useCORS: true, allowTaint: true, logging: false, - windowWidth: Math.ceil(elementWidth), - windowHeight: Math.ceil(elementHeight) + windowWidth: Math.ceil(actualElementWidth), + windowHeight: Math.ceil(actualElementHeight) }); const scaleFactor = canvas.width / contentWidth;