diff --git a/public/resume-5.html b/public/resume-5.html
index f694daa..06e4b2e 100644
--- a/public/resume-5.html
+++ b/public/resume-5.html
@@ -981,28 +981,24 @@
function loadScript(src) {
return new Promise(function (ok, fail) {
- if (window.html2pdf) { console.log('[PDF] html2pdf already loaded'); ok(); return; }
- console.log('[PDF] loading script from CDN...');
+ if (window.html2pdf) { ok(); return; }
var s = document.createElement('script');
s.src = src;
- 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); };
+ s.onload = ok;
+ s.onerror = fail;
document.head.appendChild(s);
});
}
btn.addEventListener('click', function () {
- console.log('[PDF] === click === busy:', busy);
if (busy) return;
busy = true;
btn.setAttribute('data-loading', 'true');
var doc = document.querySelector('.resume-doc');
- 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; }
+ if (!doc) { 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) {
@@ -1012,64 +1008,81 @@
c.width = img.naturalWidth;
c.height = img.naturalHeight;
c.getContext('2d').drawImage(img, 0, 0);
- 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); }
+ res(c.toDataURL('image/webp'));
+ } catch (e) { 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); };
+ photo.onload = function () { toDataURL(photo).then(res); };
+ photo.onerror = function () { res(null); };
});
} else {
- console.log('[PDF] no photo element, skipping');
photoReady = Promise.resolve(null);
}
- function cloneAndInlineStyles(original) {
- var clone = original.cloneNode(true);
+ function resolveStylesInClone(clonedDoc, original) {
+ var props = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit','content'];
+
var origEls = original.querySelectorAll('*');
- var cloneEls = clone.querySelectorAll('*');
- var allProps = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit'];
+ var cloneEls = clonedDoc.querySelectorAll('*');
for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
var cs = getComputedStyle(origEls[i]);
- for (var j = 0; j < allProps.length; j++) {
- var v = cs.getPropertyValue(allProps[j]);
- if (v) cloneEls[i].style.setProperty(allProps[j], v);
+ for (var j = 0; j < props.length; j++) {
+ var v = cs.getPropertyValue(props[j]);
+ if (v) cloneEls[i].style.setProperty(props[j], v);
}
}
- var origCs = getComputedStyle(original);
- for (var j = 0; j < allProps.length; j++) {
- var v = origCs.getPropertyValue(allProps[j]);
- if (v) clone.style.setProperty(allProps[j], v);
+
+ var rootCs = getComputedStyle(original);
+ for (var j = 0; j < props.length; j++) {
+ var v = rootCs.getPropertyValue(props[j]);
+ if (v) clonedDoc.style.setProperty(props[j], v);
+ }
+
+ var sheets = clonedDoc.styleSheets;
+ for (var s = sheets.length - 1; s >= 0; s--) {
+ try {
+ var sheet = sheets[s];
+ while (sheet.cssRules.length > 0) sheet.deleteRule(0);
+ } catch (e) {}
+ }
+ clonedDoc.querySelectorAll('style').forEach(function (el) { el.remove(); });
+ clonedDoc.querySelectorAll('link[rel="stylesheet"]').forEach(function (el) { el.remove(); });
+
+ var pseudoProps = ['content','color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','width','height','border-radius','border-width','border-style','white-space','position','top','bottom','left','right','z-index','overflow','list-style-type','object-fit'];
+ for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
+ ['::before','::after'].forEach(function(pseudo) {
+ try {
+ var cs = getComputedStyle(origEls[i], pseudo);
+ var content = cs.getPropertyValue('content');
+ if (!content || content === 'none' || content === 'normal') return;
+ var el = document.createElement('span');
+ el.style.cssText = 'display:block;margin:0;padding:0;border:none;background:none;';
+ for (var j = 0; j < pseudoProps.length; j++) {
+ var v = cs.getPropertyValue(pseudoProps[j]);
+ if (v && v !== 'normal' && v !== 'auto') el.style.setProperty(pseudoProps[j], v);
+ }
+ el.textContent = content.replace(/^["']|["']$/g, '');
+ if (pseudo === '::before') cloneEls[i].prepend(el);
+ else cloneEls[i].appendChild(el);
+ } catch (e) {}
+ });
}
- var styles = clone.querySelectorAll('style');
- for (var s = 0; s < styles.length; s++) styles[s].textContent = '';
- var links = clone.querySelectorAll('link[rel="stylesheet"]');
- for (var l = 0; l < links.length; l++) links[l].remove();
- return clone;
}
photoReady.then(function (dataUrl) {
- console.log('[PDF] step 1: photo ready');
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] step 3: fonts ready, loading html2pdf.js...');
return loadScript(CDN);
})
.then(function () {
- console.log('[PDF] step 4: html2pdf loaded, generating...');
return html2pdf().from(doc).set({
margin: 10,
filename: 'Mamadaev_Resume.pdf',
@@ -1079,41 +1092,21 @@
useCORS: true,
backgroundColor: '#fff',
onclone: function (clonedDoc) {
- console.log('[PDF] onclone: inlining styles...');
var clonedEl = clonedDoc.querySelector('.resume-doc');
if (!clonedEl) return;
- var origEls = doc.querySelectorAll('*');
- var cloneEls = clonedEl.querySelectorAll('*');
- var props = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit'];
- for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
- var cs = getComputedStyle(origEls[i]);
- for (var j = 0; j < props.length; j++) {
- var v = cs.getPropertyValue(props[j]);
- if (v) cloneEls[i].style.setProperty(props[j], v);
- }
- }
- var rootCs = getComputedStyle(doc);
- for (var j = 0; j < props.length; j++) {
- var v = rootCs.getPropertyValue(props[j]);
- if (v) clonedEl.style.setProperty(props[j], v);
- }
- clonedDoc.querySelectorAll('style').forEach(function(s){ s.textContent = ''; });
- clonedDoc.querySelectorAll('link[rel="stylesheet"]').forEach(function(l){ l.remove(); });
- console.log('[PDF] onclone: styles inlined');
+ resolveStylesInClone(clonedDoc, doc);
}
},
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
}).save();
})
- .then(function (result) {
- console.log('[PDF] step 5: generation COMPLETE, result:', result);
+ .then(function () {
if (origSrc && photo) photo.setAttribute('src', origSrc);
busy = false;
btn.removeAttribute('data-loading');
})
.catch(function (e) {
- console.error('[PDF] step ERROR:', e.message || e);
- console.error('[PDF] stack:', e.stack || 'no stack');
+ console.error('[PDF] error:', e.message || e, e.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 189da70..6277905 100644
--- a/src/pages/resume-5.html
+++ b/src/pages/resume-5.html
@@ -850,28 +850,24 @@
function loadScript(src) {
return new Promise(function (ok, fail) {
- if (window.html2pdf) { console.log('[PDF] html2pdf already loaded'); ok(); return; }
- console.log('[PDF] loading script from CDN...');
+ if (window.html2pdf) { ok(); return; }
var s = document.createElement('script');
s.src = src;
- 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); };
+ s.onload = ok;
+ s.onerror = fail;
document.head.appendChild(s);
});
}
btn.addEventListener('click', function () {
- console.log('[PDF] === click === busy:', busy);
if (busy) return;
busy = true;
btn.setAttribute('data-loading', 'true');
var doc = document.querySelector('.resume-doc');
- 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; }
+ if (!doc) { 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) {
@@ -881,64 +877,81 @@
c.width = img.naturalWidth;
c.height = img.naturalHeight;
c.getContext('2d').drawImage(img, 0, 0);
- 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); }
+ res(c.toDataURL('image/webp'));
+ } catch (e) { 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); };
+ photo.onload = function () { toDataURL(photo).then(res); };
+ photo.onerror = function () { res(null); };
});
} else {
- console.log('[PDF] no photo element, skipping');
photoReady = Promise.resolve(null);
}
- function cloneAndInlineStyles(original) {
- var clone = original.cloneNode(true);
+ function resolveStylesInClone(clonedDoc, original) {
+ var props = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit','content'];
+
var origEls = original.querySelectorAll('*');
- var cloneEls = clone.querySelectorAll('*');
- var allProps = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit'];
+ var cloneEls = clonedDoc.querySelectorAll('*');
for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
var cs = getComputedStyle(origEls[i]);
- for (var j = 0; j < allProps.length; j++) {
- var v = cs.getPropertyValue(allProps[j]);
- if (v) cloneEls[i].style.setProperty(allProps[j], v);
+ for (var j = 0; j < props.length; j++) {
+ var v = cs.getPropertyValue(props[j]);
+ if (v) cloneEls[i].style.setProperty(props[j], v);
}
}
- var origCs = getComputedStyle(original);
- for (var j = 0; j < allProps.length; j++) {
- var v = origCs.getPropertyValue(allProps[j]);
- if (v) clone.style.setProperty(allProps[j], v);
+
+ var rootCs = getComputedStyle(original);
+ for (var j = 0; j < props.length; j++) {
+ var v = rootCs.getPropertyValue(props[j]);
+ if (v) clonedDoc.style.setProperty(props[j], v);
+ }
+
+ var sheets = clonedDoc.styleSheets;
+ for (var s = sheets.length - 1; s >= 0; s--) {
+ try {
+ var sheet = sheets[s];
+ while (sheet.cssRules.length > 0) sheet.deleteRule(0);
+ } catch (e) {}
+ }
+ clonedDoc.querySelectorAll('style').forEach(function (el) { el.remove(); });
+ clonedDoc.querySelectorAll('link[rel="stylesheet"]').forEach(function (el) { el.remove(); });
+
+ var pseudoProps = ['content','color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','width','height','border-radius','border-width','border-style','white-space','position','top','bottom','left','right','z-index','overflow','list-style-type','object-fit'];
+ for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
+ ['::before','::after'].forEach(function(pseudo) {
+ try {
+ var cs = getComputedStyle(origEls[i], pseudo);
+ var content = cs.getPropertyValue('content');
+ if (!content || content === 'none' || content === 'normal') return;
+ var el = document.createElement('span');
+ el.style.cssText = 'display:block;margin:0;padding:0;border:none;background:none;';
+ for (var j = 0; j < pseudoProps.length; j++) {
+ var v = cs.getPropertyValue(pseudoProps[j]);
+ if (v && v !== 'normal' && v !== 'auto') el.style.setProperty(pseudoProps[j], v);
+ }
+ el.textContent = content.replace(/^["']|["']$/g, '');
+ if (pseudo === '::before') cloneEls[i].prepend(el);
+ else cloneEls[i].appendChild(el);
+ } catch (e) {}
+ });
}
- var styles = clone.querySelectorAll('style');
- for (var s = 0; s < styles.length; s++) styles[s].textContent = '';
- var links = clone.querySelectorAll('link[rel="stylesheet"]');
- for (var l = 0; l < links.length; l++) links[l].remove();
- return clone;
}
photoReady.then(function (dataUrl) {
- console.log('[PDF] step 1: photo ready');
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] step 3: fonts ready, loading html2pdf.js...');
return loadScript(CDN);
})
.then(function () {
- console.log('[PDF] step 4: html2pdf loaded, generating...');
return html2pdf().from(doc).set({
margin: 10,
filename: 'Mamadaev_Resume.pdf',
@@ -948,41 +961,21 @@
useCORS: true,
backgroundColor: '#fff',
onclone: function (clonedDoc) {
- console.log('[PDF] onclone: inlining styles...');
var clonedEl = clonedDoc.querySelector('.resume-doc');
if (!clonedEl) return;
- var origEls = doc.querySelectorAll('*');
- var cloneEls = clonedEl.querySelectorAll('*');
- var props = ['color','background-color','background','border-color','border-top-color','border-bottom-color','border-left-color','border-right-color','box-shadow','opacity','font-family','font-size','font-weight','line-height','letter-spacing','text-align','text-decoration','text-transform','padding','padding-top','padding-bottom','padding-left','padding-right','margin','margin-top','margin-bottom','margin-left','margin-right','display','flex-direction','align-items','justify-content','gap','grid-template-columns','grid-column','width','height','min-width','min-height','max-width','max-height','position','top','bottom','left','right','z-index','overflow','border-radius','border-width','border-style','white-space','list-style-type','object-fit'];
- for (var i = 0; i < origEls.length && i < cloneEls.length; i++) {
- var cs = getComputedStyle(origEls[i]);
- for (var j = 0; j < props.length; j++) {
- var v = cs.getPropertyValue(props[j]);
- if (v) cloneEls[i].style.setProperty(props[j], v);
- }
- }
- var rootCs = getComputedStyle(doc);
- for (var j = 0; j < props.length; j++) {
- var v = rootCs.getPropertyValue(props[j]);
- if (v) clonedEl.style.setProperty(props[j], v);
- }
- clonedDoc.querySelectorAll('style').forEach(function(s){ s.textContent = ''; });
- clonedDoc.querySelectorAll('link[rel="stylesheet"]').forEach(function(l){ l.remove(); });
- console.log('[PDF] onclone: styles inlined');
+ resolveStylesInClone(clonedDoc, doc);
}
},
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
}).save();
})
- .then(function (result) {
- console.log('[PDF] step 5: generation COMPLETE, result:', result);
+ .then(function () {
if (origSrc && photo) photo.setAttribute('src', origSrc);
busy = false;
btn.removeAttribute('data-loading');
})
.catch(function (e) {
- console.error('[PDF] step ERROR:', e.message || e);
- console.error('[PDF] stack:', e.stack || 'no stack');
+ console.error('[PDF] error:', e.message || e, e.stack || '');
if (origSrc && photo) photo.setAttribute('src', origSrc);
busy = false;
btn.removeAttribute('data-loading');