From 1b53e67d906518e6c56a310c47bb65c4887f03e9 Mon Sep 17 00:00:00 2001 From: Local Build Date: Thu, 13 Aug 2026 20:53:04 +0200 Subject: [PATCH] debug(pdf): add detailed step-by-step console logging --- public/resume-5.html | 53 +++++++++++++++++++++++++++-------------- src/pages/resume-5.html | 53 +++++++++++++++++++++++++++-------------- 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/public/resume-5.html b/public/resume-5.html index 765174f..3eb9494 100644 --- a/public/resume-5.html +++ b/public/resume-5.html @@ -981,25 +981,28 @@ function loadScript(src) { return new Promise(function (ok, fail) { - if (window.html2pdf) { ok(); return; } + if (window.html2pdf) { console.log('[PDF] html2pdf already loaded'); ok(); return; } + console.log('[PDF] loading script from CDN...'); var s = document.createElement('script'); s.src = src; - s.onload = ok; - s.onerror = fail; + s.onload = function () { console.log('[PDF] CDN script loaded OK'); ok(); }; + s.onerror = function (e) { console.error('[PDF] CDN script FAILED to load', e); fail(e); }; document.head.appendChild(s); }); } btn.addEventListener('click', function () { - console.log('[PDF] click, busy:', busy); + console.log('[PDF] === click === busy:', busy); if (busy) return; busy = true; btn.setAttribute('data-loading', 'true'); var doc = document.querySelector('.resume-doc'); - if (!doc) { busy = false; btn.removeAttribute('data-loading'); return; } + console.log('[PDF] doc element:', !!doc, doc ? doc.className : 'N/A'); + if (!doc) { console.error('[PDF] .resume-doc not found!'); busy = false; btn.removeAttribute('data-loading'); return; } var photo = doc.querySelector('.resume-photo'); + console.log('[PDF] photo element:', !!photo, photo ? { complete: photo.complete, naturalWidth: photo.naturalWidth, src: photo.src } : 'N/A'); var origSrc = photo ? photo.getAttribute('src') : null; function toDataURL(img) { @@ -1009,29 +1012,41 @@ c.width = img.naturalWidth; c.height = img.naturalHeight; c.getContext('2d').drawImage(img, 0, 0); - res(c.toDataURL('image/webp')); - } catch (e) { res(null); } + var url = c.toDataURL('image/webp'); + console.log('[PDF] toDataURL OK, length:', url.length); + res(url); + } catch (e) { console.error('[PDF] toDataURL FAILED:', e); res(null); } }); } - var photoReady = photo && photo.complete && photo.naturalWidth > 0 - ? toDataURL(photo) - : new Promise(function (res) { - photo.onload = function () { toDataURL(photo).then(res); }; - photo.onerror = function () { res(null); }; - }); + var photoReady; + if (photo && photo.complete && photo.naturalWidth > 0) { + console.log('[PDF] photo already loaded, converting...'); + photoReady = toDataURL(photo); + } else if (photo) { + console.log('[PDF] photo not loaded yet, waiting...'); + photoReady = new Promise(function (res) { + photo.onload = function () { console.log('[PDF] photo onload fired'); toDataURL(photo).then(res); }; + photo.onerror = function (e) { console.error('[PDF] photo onerror:', e); res(null); }; + }); + } else { + console.log('[PDF] no photo element, skipping'); + photoReady = Promise.resolve(null); + } photoReady.then(function (dataUrl) { - console.log('[PDF] photo ready, dataUrl:', !!dataUrl); + console.log('[PDF] step 1: photo ready, dataUrl:', dataUrl ? 'yes (' + dataUrl.length + ' chars)' : 'null'); if (dataUrl && photo) photo.setAttribute('src', dataUrl); + console.log('[PDF] step 2: waiting for fonts...'); return document.fonts ? document.fonts.ready : Promise.resolve(); }) .then(function () { - console.log('[PDF] fonts ready, loading script...'); + console.log('[PDF] step 3: fonts ready, loading html2pdf.js...'); return loadScript(CDN); }) .then(function () { - console.log('[PDF] script loaded, generating...'); + console.log('[PDF] step 4: html2pdf loaded, type:', typeof html2pdf); + console.log('[PDF] step 4: starting generation...'); return html2pdf().from(doc).set({ margin: 10, filename: 'Mamadaev_Resume.pdf', @@ -1040,13 +1055,15 @@ jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } }); }) - .then(function () { + .then(function (result) { + console.log('[PDF] step 5: generation COMPLETE, result:', result); if (origSrc && photo) photo.setAttribute('src', origSrc); busy = false; btn.removeAttribute('data-loading'); }) .catch(function (e) { - console.error('PDF error:', e); + console.error('[PDF] step ERROR:', e.message || e); + console.error('[PDF] stack:', e.stack || 'no stack'); if (origSrc && photo) photo.setAttribute('src', origSrc); busy = false; btn.removeAttribute('data-loading'); diff --git a/src/pages/resume-5.html b/src/pages/resume-5.html index 3512f5d..2f7be4f 100644 --- a/src/pages/resume-5.html +++ b/src/pages/resume-5.html @@ -850,25 +850,28 @@ function loadScript(src) { return new Promise(function (ok, fail) { - if (window.html2pdf) { ok(); return; } + if (window.html2pdf) { console.log('[PDF] html2pdf already loaded'); ok(); return; } + console.log('[PDF] loading script from CDN...'); var s = document.createElement('script'); s.src = src; - s.onload = ok; - s.onerror = fail; + s.onload = function () { console.log('[PDF] CDN script loaded OK'); ok(); }; + s.onerror = function (e) { console.error('[PDF] CDN script FAILED to load', e); fail(e); }; document.head.appendChild(s); }); } btn.addEventListener('click', function () { - console.log('[PDF] click, busy:', busy); + console.log('[PDF] === click === busy:', busy); if (busy) return; busy = true; btn.setAttribute('data-loading', 'true'); var doc = document.querySelector('.resume-doc'); - if (!doc) { busy = false; btn.removeAttribute('data-loading'); return; } + console.log('[PDF] doc element:', !!doc, doc ? doc.className : 'N/A'); + if (!doc) { console.error('[PDF] .resume-doc not found!'); busy = false; btn.removeAttribute('data-loading'); return; } var photo = doc.querySelector('.resume-photo'); + console.log('[PDF] photo element:', !!photo, photo ? { complete: photo.complete, naturalWidth: photo.naturalWidth, src: photo.src } : 'N/A'); var origSrc = photo ? photo.getAttribute('src') : null; function toDataURL(img) { @@ -878,29 +881,41 @@ c.width = img.naturalWidth; c.height = img.naturalHeight; c.getContext('2d').drawImage(img, 0, 0); - res(c.toDataURL('image/webp')); - } catch (e) { res(null); } + var url = c.toDataURL('image/webp'); + console.log('[PDF] toDataURL OK, length:', url.length); + res(url); + } catch (e) { console.error('[PDF] toDataURL FAILED:', e); res(null); } }); } - var photoReady = photo && photo.complete && photo.naturalWidth > 0 - ? toDataURL(photo) - : new Promise(function (res) { - photo.onload = function () { toDataURL(photo).then(res); }; - photo.onerror = function () { res(null); }; - }); + var photoReady; + if (photo && photo.complete && photo.naturalWidth > 0) { + console.log('[PDF] photo already loaded, converting...'); + photoReady = toDataURL(photo); + } else if (photo) { + console.log('[PDF] photo not loaded yet, waiting...'); + photoReady = new Promise(function (res) { + photo.onload = function () { console.log('[PDF] photo onload fired'); toDataURL(photo).then(res); }; + photo.onerror = function (e) { console.error('[PDF] photo onerror:', e); res(null); }; + }); + } else { + console.log('[PDF] no photo element, skipping'); + photoReady = Promise.resolve(null); + } photoReady.then(function (dataUrl) { - console.log('[PDF] photo ready, dataUrl:', !!dataUrl); + console.log('[PDF] step 1: photo ready, dataUrl:', dataUrl ? 'yes (' + dataUrl.length + ' chars)' : 'null'); if (dataUrl && photo) photo.setAttribute('src', dataUrl); + console.log('[PDF] step 2: waiting for fonts...'); return document.fonts ? document.fonts.ready : Promise.resolve(); }) .then(function () { - console.log('[PDF] fonts ready, loading script...'); + console.log('[PDF] step 3: fonts ready, loading html2pdf.js...'); return loadScript(CDN); }) .then(function () { - console.log('[PDF] script loaded, generating...'); + console.log('[PDF] step 4: html2pdf loaded, type:', typeof html2pdf); + console.log('[PDF] step 4: starting generation...'); return html2pdf().from(doc).set({ margin: 10, filename: 'Mamadaev_Resume.pdf', @@ -909,13 +924,15 @@ jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } }); }) - .then(function () { + .then(function (result) { + console.log('[PDF] step 5: generation COMPLETE, result:', result); if (origSrc && photo) photo.setAttribute('src', origSrc); busy = false; btn.removeAttribute('data-loading'); }) .catch(function (e) { - console.error('PDF error:', e); + console.error('[PDF] step ERROR:', e.message || e); + console.error('[PDF] stack:', e.stack || 'no stack'); if (origSrc && photo) photo.setAttribute('src', origSrc); busy = false; btn.removeAttribute('data-loading');