ساخت رزومه حرفه‌ای

رزومه حرفه‌ای خودت را بساز

اطلاعاتت را وارد کن و یک رزومه حرفه‌ای، مرتب و آماده ارائه بساز.

01

اطلاعات شخصی

اطلاعات پایه خودت را وارد کن.

سایز پیشنهادی: ۳۰۰ × ۳۰۰ پیکسل · فقط یک تصویر مجاز است؛ برای انتخاب تصویر جدید ابتدا تصویر فعلی را حذف کن.
02

درباره خودت

خودت را کوتاه و حرفه‌ای معرفی کن.

03

اطلاعات تماس

راه‌های ارتباطی خودت را وارد کن.

04

سوابق کاری

تجربه‌های شغلی خودت را اضافه کن.

05

مهارت‌ها

مهارت‌های حرفه‌ای خودت را اضافه کن.

06

پروژه‌ها

پروژه‌های مهم خودت را معرفی کن.

07

زبان‌ها

زبان‌هایی که می‌دانی و سطح آن‌ها را انتخاب کن.

آماده ساخت رزومه‌ای؟

اطلاعاتت را بررسی کن و رزومه حرفه‌ای خودت را بساز.

`; } /* ===================================================== RESUME TEMPLATE 3 — DARK CREATIVE GRID Inspired by the uploaded reference image. ====================================================== */ function createResumeDocumentTemplate3(data) { const fullName = ( escapeHtml(data.firstName) + " " + escapeHtml(data.lastName) ).trim() || "نام و نام خانوادگی"; const birthDate = ( data.birthDay || data.birthMonth || data.birthYear ) ? [ escapeHtml(data.birthDay), escapeHtml(data.birthMonth), escapeHtml(data.birthYear) ] .filter(Boolean) .join(" / ") : ""; const profilePhotoHtml = data.photo ? `
تصویر پروفایل
` : ""; const contactItems = []; if (data.phone) { contactItems.push(`
شماره تماس ${escapeHtml(data.phone)}
`); } if (data.email) { contactItems.push(`
ایمیل ${escapeHtml(data.email)}
`); } if (data.linkedin) { contactItems.push(` `); } if (data.github) { contactItems.push(` `); } if (data.instagram) { contactItems.push(` `); } if (data.youtube) { contactItems.push(` `); } const personalItems = []; if (birthDate) { personalItems.push(`
تاریخ تولد ${birthDate}
`); } if (data.gender) { personalItems.push(`
جنسیت ${escapeHtml(data.gender)}
`); } if (data.marital) { personalItems.push(`
وضعیت تأهل ${escapeHtml(data.marital)}
`); } if (data.military) { personalItems.push(`
نظام وظیفه ${escapeHtml(data.military)}
`); } if (data.province || data.city) { personalItems.push(`
محل سکونت ${[ data.province, data.city ].filter(Boolean).map(escapeHtml).join("، ")}
`); } const skillsHtml = data.skills.length ? data.skills.map(function (skill) { return ` ${escapeHtml(skill)} `; }).join("") : `مهارتی ثبت نشده است.`; const languagesHtml = data.languages.length ? data.languages.map(function (language) { return ` ${escapeHtml(language)} `; }).join("") : `زبانی ثبت نشده است.`; const validExperiences = data.experiences.filter(function (item) { return item.company || item.description; }); const experiencesHtml = validExperiences.length ? validExperiences.map(function (item) { const meta = [ item.city, item.type, item.start, item.current ? "در حال همکاری" : item.end ] .filter(Boolean) .map(escapeHtml) .join(" · "); return `

${escapeHtml(item.company) || "سابقه شغلی"}

${ meta ? `
${meta}
` : "" }
${ item.description ? `

${escapeHtml(item.description)}

` : "" }
`; }).join("") : `
سابقه کاری ثبت نشده است.
`; const validProjects = data.projects.filter(function (item) { return item.title || item.description; }); const projectsHtml = validProjects.length ? validProjects.map(function (item) { return ` `; }).join("") : `
پروژه‌ای ثبت نشده است.
`; return ` رزومه ${fullName}
رزومه حرفه‌ای

${fullName}

${ data.jobTitle ? `
${escapeHtml(data.jobTitle)}
` : "" }
${profilePhotoHtml}
${ data.about ? `

درباره من

${escapeHtml(data.about)}

` : "" }
${ contactItems.length ? `

اطلاعات تماس

${contactItems.join("")}
` : "" } ${ personalItems.length ? `

اطلاعات شخصی

${personalItems.join("")}
` : "" }

مهارت‌ها

${skillsHtml}

زبان‌ها

${languagesHtml}

سوابق کاری

${experiencesHtml}

پروژه‌ها

${projectsHtml}
`; } /* ===================================================== TEMPLATE DISPATCHER ====================================================== */ function createResumeDocument(data) { let html = ""; if (selectedResumeTemplate === "template-3") { html = createResumeDocumentTemplate3(data); } else if (selectedResumeTemplate === "template-2") { html = createResumeDocumentTemplate2(data); } else { html = createResumeDocumentTemplate1(data); } return translatePreviewHtml(html); } function createResumeDocumentTemplate1(data) { const fullName = ( escapeHtml(data.firstName) + " " + escapeHtml(data.lastName) ).trim(); const birthDate = ( data.birthDay || data.birthMonth || data.birthYear ) ? [ escapeHtml(data.birthDay), escapeHtml(data.birthMonth), escapeHtml(data.birthYear) ] .filter(Boolean) .join(" / ") : ""; const profilePhotoHtml = data.photo ? `
تصویر پروفایل
` : ""; /* CONTACT */ const contactItems = []; if (data.phone) { contactItems.push(` تلفن ${escapeHtml(data.phone)} `); } if (data.email) { contactItems.push(` ایمیل ${escapeHtml(data.email)} `); } if (data.linkedin) { contactItems.push(` LinkedIn ${escapeHtml(data.linkedin)} `); } if (data.github) { contactItems.push(` GitHub ${escapeHtml(data.github)} `); } if (data.instagram) { contactItems.push(` Instagram ${escapeHtml(data.instagram)} `); } if (data.youtube) { contactItems.push(` YouTube ${escapeHtml(data.youtube)} `); } /* EXPERIENCES */ const validExperiences = data.experiences.filter(function (item) { return ( item.company || item.description ); }); const experiencesHtml = validExperiences.length ? validExperiences .map(function (item) { const meta = [ item.city, item.type, item.start, item.current ? "در حال همکاری" : item.end ] .filter(Boolean) .map(escapeHtml) .join(" | "); return `

${ escapeHtml(item.company) || "سابقه شغلی" }

${ meta ? `
${meta}
` : "" }
${ item.description ? `

${escapeHtml( item.description )}

` : "" }
`; }) .join("") : `
سابقه کاری ثبت نشده است.
`; /* PROJECTS */ const validProjects = data.projects.filter(function (item) { return ( item.title || item.description ); }); const projectsHtml = validProjects.length ? validProjects .map(function (item) { return `

${ escapeHtml(item.title) || "پروژه" }

${ item.time ? `
${escapeHtml( item.time )}
` : "" }
${ item.description ? `

${escapeHtml( item.description )}

` : "" } ${ item.url ? ` ${escapeHtml(item.url)} ` : "" }
`; }) .join("") : `
پروژه‌ای ثبت نشده است.
`; /* SKILLS */ const skillsHtml = data.skills.length ? data.skills .map(function (skill) { return ` ${escapeHtml(skill)} `; }) .join("") : ` مهارتی ثبت نشده است. `; /* LANGUAGES */ const languagesHtml = data.languages.length ? data.languages .map(function (language) { return ` ${escapeHtml(language)} `; }) .join("") : ` زبانی ثبت نشده است. `; /* PERSONAL */ const personalInfo = []; if (birthDate) { personalInfo.push(`
تاریخ تولد ${birthDate}
`); } if (data.gender) { personalInfo.push(`
جنسیت ${escapeHtml(data.gender)}
`); } if (data.marital) { personalInfo.push(`
وضعیت تأهل ${escapeHtml(data.marital)}
`); } if (data.military) { personalInfo.push(`
نظام وظیفه ${escapeHtml(data.military)}
`); } if ( data.province || data.city ) { const location = [ data.province, data.city ] .filter(Boolean) .map(escapeHtml) .join("، "); personalInfo.push(`
محل سکونت ${location}
`); } /* =================================================== COMPLETE DOCUMENT ==================================================== */ return ` رزومه ${fullName}
${profilePhotoHtml}

${fullName}

${ data.jobTitle ? `
${escapeHtml(data.jobTitle)}
` : "" } ${ contactItems.length ? `
${contactItems.join("")}
` : "" }
${ personalInfo.length ? `
اطلاعات شخصی
${personalInfo.join("")}
` : "" } ${ data.about ? `
درباره من

${escapeHtml(data.about)}

` : "" }
سوابق کاری
${experiencesHtml}
مهارت‌ها
${skillsHtml}
پروژه‌ها
${projectsHtml}
زبان‌ها
${languagesHtml}
`; } /* ===================================================== FONT / SITE STYLES FOR PRINT ====================================================== */ function getSiteFontFamily() { const candidates = [ root, document.body, document.documentElement ]; for ( let i = 0; i < candidates.length; i++ ) { try { const computed = window.getComputedStyle( candidates[i] ); const fontFamily = computed.fontFamily; if ( fontFamily && fontFamily.trim() ) { return fontFamily; } } catch (error) {} } return "sans-serif"; } function getSiteStylesForPrint() { const links = []; const styles = []; document .querySelectorAll( 'link[rel="stylesheet"]' ) .forEach(function (link) { const href = link.href; if ( href && !links.includes(href) ) { links.push(href); } }); document .querySelectorAll("style") .forEach(function (style) { const text = style.textContent || ""; if ( text && !styles.includes(text) ) { styles.push(text); } }); return { links: links, styles: styles }; } function preparePrintHtml(html) { const fontFamily = getSiteFontFamily(); const siteStyles = getSiteStylesForPrint(); const parser = new DOMParser(); const doc = parser.parseFromString( html, "text/html" ); /* لینک‌های CSS سایت */ siteStyles.links.forEach( function (href) { const link = doc.createElement( "link" ); link.rel = "stylesheet"; link.href = href; doc.head.appendChild( link ); } ); /* فونت فعلی صفحه سایت */ const fontStyle = doc.createElement( "style" ); fontStyle.textContent = ` html, body, .resume, .resume *, .rt2-resume, .rt2-resume *, .rt3-resume, .rt3-resume * { font-family: ${fontFamily} !important; } @media print { html, body, .resume, .resume *, .rt2-resume, .rt2-resume *, .rt3-resume, .rt3-resume * { font-family: ${fontFamily} !important; } } `; doc.head.appendChild( fontStyle ); return ( "" + doc.documentElement.outerHTML ); } /* ===================================================== RENDER PREVIEW ====================================================== */ function renderPreviewDocument(html) { previewA4.innerHTML = ""; const parser = new DOMParser(); const parsed = parser.parseFromString( html, "text/html" ); /* Style */ const styles = parsed.head.querySelectorAll( "style" ); styles.forEach(function (style) { const clonedStyle = document.createElement("style"); clonedStyle.textContent = style.textContent; previewA4.appendChild( clonedStyle ); }); const languageStyle = document.createElement("style"); languageStyle.textContent = currentFormLanguage === "en" ? ` .resume, .rt2-resume, .rt3-resume{ direction:ltr !important; } .resume, .rt2-resume, .rt3-resume, .resume *, .rt2-resume *, .rt3-resume *{ text-align:left; } .resume .contact-item, .resume .contact-item *, .rt2-resume .rt2-contact-item, .rt2-resume .rt2-contact-item *, .rt3-resume .rt3-contact, .rt3-resume .rt3-contact *{ direction:ltr; text-align:left; } .resume .section-title, .rt2-resume .rt2-section-title, .rt3-resume .rt3-section-title{ text-align:left; } .resume .profile-photo-wrap{ margin-left:auto; margin-right:0; } ` : ` .resume, .rt2-resume, .rt3-resume{ direction:rtl !important; } `; previewA4.appendChild(languageStyle); /* Body */ Array.from( parsed.body.childNodes ) .forEach(function (node) { previewA4.appendChild( document.importNode( node, true ) ); }); /* اطمینان از رنگ انتخاب‌شده */ applyPreviewColor( selectedResumeColor ); } /* ===================================================== COLOR SELECTION ====================================================== */ function applyPreviewColor(color) { if (!color) { return; } selectedResumeColor = color; const resume = previewA4.querySelector( ".resume" ); const template2 = previewA4.querySelector( ".rt2-resume" ); if (template2) { template2.style.setProperty( "--rt2-accent", color ); } const template3 = previewA4.querySelector( ".rt3-resume" ); if (template3) { template3.style.setProperty( "--rt3-accent", color ); } if (resume) { resume.style.setProperty( "--resume-color", color ); } /* * برای مرورگرهایی که color-mix را پشتیبانی نمی‌کنند، * رنگ‌های مهم مستقیماً با JS اعمال می‌شوند. */ const titleElements = previewA4.querySelectorAll( ".section-title" ); titleElements.forEach( function (element) { element.style.color = color; element.style.borderRightColor = color; } ); const jobTitle = previewA4.querySelector( ".job-title" ); if (jobTitle) { jobTitle.style.color = color; } const dots = previewA4.querySelectorAll( ".timeline-dot" ); dots.forEach( function (dot) { dot.style.backgroundColor = color; dot.style.boxShadow = "0 0 0 1px " + color; } ); const links = previewA4.querySelectorAll( ".project-link" ); links.forEach( function (link) { link.style.color = color; } ); const template3AccentElements = previewA4.querySelectorAll( ".rt3-job, .rt3-dot, .rt3-section-title, .rt3-project-link, .rt3-project-link-icon, .rt3-project-link-arrow" ); template3AccentElements.forEach( function (element) { if ( element.classList.contains("rt3-dot") ) { element.style.backgroundColor = color; } else { element.style.color = color; } } ); const template3AccentBorders = previewA4.querySelectorAll( ".rt3-photo, .rt3-tag, .rt3-project-link, .rt3-project-link-icon" ); template3AccentBorders.forEach( function (element) { element.style.borderColor = color; } ); const skills = previewA4.querySelectorAll( ".skill" ); skills.forEach( function (skill) { skill.style.color = color; skill.style.borderColor = color; } ); const languages = previewA4.querySelectorAll( ".language" ); languages.forEach( function (language) { language.style.color = color; language.style.borderColor = color; } ); } const colorOptions = document.querySelectorAll( ".kdx-resume-color-option" ); colorOptions.forEach( function (button) { button.addEventListener( "click", function (event) { event.preventDefault(); const color = this.dataset.color; if (!color) { return; } colorOptions.forEach( function (item) { item.classList.remove( "is-active" ); } ); this.classList.add( "is-active" ); applyPreviewColor( color ); } ); } ); /* ===================================================== TEMPLATE SELECTION ====================================================== */ const templateOptions = document.querySelectorAll( ".kdx-resume-template-option" ); function setActiveResumeTemplate(templateName) { if ( templateName !== "template-1" && templateName !== "template-2" && templateName !== "template-3" ) { templateName = "template-1"; } selectedResumeTemplate = templateName; templateOptions.forEach( function (button) { const isActive = button.dataset.template === selectedResumeTemplate; button.classList.toggle( "is-active", isActive ); button.setAttribute( "aria-pressed", isActive ? "true" : "false" ); } ); /* * اگر کاربر بعد از ساخت رزومه قالب را عوض کند، * بدون نیاز به کلیک دوباره روی «ساخت رزومه» * همان اطلاعات فوراً با قالب جدید رندر می‌شود. */ if (lastResumeData) { renderPreviewDocument( createResumeDocument( lastResumeData ) ); kdxSafeRequestAnimationFrame( function () { scaleMobilePreview(); } ); } } templateOptions.forEach( function (button) { button.addEventListener( "click", function (event) { event.preventDefault(); setActiveResumeTemplate( this.dataset.template ); } ); } ); /* ===================================================== MOBILE SCALE ====================================================== */ function scaleMobilePreview() { if ( window.innerWidth > 720 ) { previewA4.style.transform = ""; previewA4.style.transformOrigin = ""; previewA4.style.marginBottom = ""; return; } const body = document.querySelector( ".kdx-resume-preview-body" ); if (!body) { return; } /* * MOBILE PREVIEW FIX * Keep the A4 resume completely inside the mobile viewport. * The scale is calculated from the real available width after * body padding, so the resume cannot overflow horizontally. */ const bodyStyle = window.getComputedStyle(body); const paddingLeft = parseFloat(bodyStyle.paddingLeft) || 0; const paddingRight = parseFloat(bodyStyle.paddingRight) || 0; const availableWidth = Math.max(1, body.clientWidth - paddingLeft - paddingRight); const a4Width = 793.7008; const a4Height = 1122.5197; const scale = Math.min( 1, availableWidth / a4Width ); previewA4.style.width = a4Width + "px"; previewA4.style.minHeight = a4Height + "px"; previewA4.style.transformOrigin = "top center"; previewA4.style.transform = "scale(" + scale + ")"; /* Compensate for the visual height removed by transform. */ previewA4.style.marginBottom = "-" + ( a4Height * (1 - scale) ) + "px"; } /* ===================================================== OPEN PREVIEW ====================================================== */ function openResumePreview(data) { lastResumeData = data; const html = createResumeDocument(data); renderPreviewDocument(html); preview.classList.toggle( "kdx-preview-en", currentFormLanguage === "en" ); preview.classList.add( "kdx-preview-visible" ); preview.setAttribute( "aria-hidden", "false" ); document.body.style.overflow = "hidden"; kdxSafeRequestAnimationFrame(function () { scaleMobilePreview(); }); } /* ===================================================== CLOSE PREVIEW ====================================================== */ function closeResumePreview() { preview.classList.remove( "kdx-preview-visible" ); preview.setAttribute( "aria-hidden", "true" ); document.body.style.overflow = ""; } const closeButton = document.getElementById( "kdx-preview-close" ); if (closeButton) { closeButton.addEventListener( "click", function (event) { event.preventDefault(); closeResumePreview(); } ); } /* ===================================================== ESC ====================================================== */ document.addEventListener( "keydown", function (event) { if ( event.key === "Escape" && preview.classList.contains( "kdx-preview-visible" ) ) { closeResumePreview(); } } ); /* ===================================================== PRINT / BROWSER COMPATIBILITY HELPERS ====================================================== */ function kdxWaitForFonts(doc, callback) { if (!doc || !callback) { return; } try { if (doc.fonts && doc.fonts.ready && typeof doc.fonts.ready.then === "function") { doc.fonts.ready.then(function () { callback(); }).catch(function () { callback(); }); return; } } catch (error) {} callback(); } function kdxSafeRequestAnimationFrame(callback) { if (typeof window.requestAnimationFrame === "function") { window.requestAnimationFrame(callback); } else { window.setTimeout(callback, 16); } } /* ===================================================== PRINT ====================================================== */ function printResume(html) { const preparedHtml = preparePrintHtml(html); let printed = false; function fallback() { if (printed) return; printUsingIframe(preparedHtml); } /* * ابتدا از Blob URL استفاده می‌کنیم. * این روش به سند about:blank و document.write وابسته نیست و * محتوای رزومه تولیدشده را از کش صفحه اصلی جدا نگه می‌دارد. */ try { if ( window.Blob && window.URL && typeof window.URL.createObjectURL === "function" ) { const blob = new Blob( [preparedHtml], { type: "text/html;charset=utf-8" } ); const blobUrl = window.URL.createObjectURL(blob); let printWindow = null; try { printWindow = window.open( blobUrl, "_blank", "width=1000,height=1000" ); } catch (error) { printWindow = null; } if (printWindow) { const doPrint = function () { if (printed) return; printed = true; kdxWaitForFonts( printWindow.document, function () { setTimeout(function () { try { printWindow.focus(); printWindow.print(); } catch (error) { printed = false; try { printWindow.close(); } catch (closeError) {} fallback(); } setTimeout(function () { try { window.URL.revokeObjectURL(blobUrl); } catch (error) {} }, 5000); }, 350); } ); }; if (printWindow.document && printWindow.document.readyState === "complete") { setTimeout(doPrint, 400); } else { printWindow.onload = function () { setTimeout(doPrint, 400); }; /* بعضی مرورگرها onload پنجره Blob را دیر یا ناقص گزارش می‌کنند. */ setTimeout(doPrint, 2200); } return; } try { window.URL.revokeObjectURL(blobUrl); } catch (error) {} } } catch (error) { console.warn("KDX Resume Print: Blob mode failed; using iframe fallback.", error); } fallback(); } /* ===================================================== IFRAME PRINT FALLBACK ====================================================== */ function printUsingIframe(html) { const iframe = document.createElement("iframe"); iframe.setAttribute("title", "Kardid Resume Print"); iframe.setAttribute("aria-hidden", "true"); iframe.style.position = "fixed"; iframe.style.left = "-10000px"; iframe.style.top = "0"; iframe.style.width = "210mm"; iframe.style.height = "297mm"; iframe.style.border = "0"; iframe.style.visibility = "hidden"; iframe.style.opacity = "0"; iframe.style.pointerEvents = "none"; document.body.appendChild(iframe); let printed = false; function cleanup() { setTimeout(function () { if (iframe && iframe.parentNode) { iframe.parentNode.removeChild(iframe); } }, 3500); } function executePrint() { if (printed) return; printed = true; try { const iframeWindow = iframe.contentWindow; const iframeDoc = iframe.contentDocument || (iframeWindow ? iframeWindow.document : null); if (!iframeWindow || !iframeDoc) { cleanup(); return; } kdxWaitForFonts(iframeDoc, function () { setTimeout(function () { try { iframeWindow.focus(); iframeWindow.print(); } catch (error) { console.error("KDX Resume Print Error:", error); } cleanup(); }, 250); }); } catch (error) { console.error("KDX Resume Print Error:", error); cleanup(); } } try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; iframeDoc.open(); iframeDoc.write(html); iframeDoc.close(); } catch (error) { cleanup(); return; } iframe.onload = function () { setTimeout(executePrint, 500); }; setTimeout(executePrint, 1800); } const printButton = document.getElementById( "kdx-preview-print" ); if (printButton) { printButton.addEventListener( "click", function (event) { event.preventDefault(); const data = collectResumeData(); const html = createResumeDocument(data); printResume(html); } ); } /* ===================================================== CREATE ====================================================== */ const createButton = $("#kdx-resume-create"); if (createButton) { createButton.addEventListener( "click", function (event) { event.preventDefault(); try { const data = collectResumeData(); if ( !validateResume(data) ) { return; } openResumePreview( data ); showMessage( "رزومه با موفقیت آماده شد.", "success" ); } catch (error) { console.error( "KDX Resume Builder Error:", error ); showMessage( "هنگام ساخت رزومه خطایی رخ داد. صفحه را یک‌بار تازه‌سازی کن.", "error" ); } } ); } /* ===================================================== RESIZE ====================================================== */ window.addEventListener( "resize", function () { if ( preview.classList.contains( "kdx-preview-visible" ) ) { scaleMobilePreview(); } } ); /* ===================================================== INITIAL EXPERIENCE ====================================================== */ addExperience(); } /* ======================================================= DOM READY ======================================================== */ if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", initKDXResumeBuilder ); } else { initKDXResumeBuilder(); } })();