diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index ebafa41..e4a5c21 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 @@ -2586,13 +2594,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 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 / actualElementWidth, + MAX_PDF_CANVAS_DIMENSION / actualElementHeight + ); + 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, + 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(actualElementWidth), + windowHeight: Math.ceil(actualElementHeight) }); const scaleFactor = canvas.width / contentWidth; diff --git a/script.js b/script.js index ebafa41..e4a5c21 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 @@ -2586,13 +2594,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 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 / actualElementWidth, + MAX_PDF_CANVAS_DIMENSION / actualElementHeight + ); + 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, + 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(actualElementWidth), + windowHeight: Math.ceil(actualElementHeight) }); const scaleFactor = canvas.width / contentWidth;