import { escapeHtml, sanitizeUrl } from "./security"; import type { CoverLetterData, ResumeData } from "./types"; export function generateResumeHTML(data: ResumeData): string { const templateStyles = getTemplateStyles(data.template); const layoutStyles = getLayoutStyles(data.layout); const fontFamily = getFontFamily(data.font); const fontSizes = getFontSizes(data.fontSize); const spacingValue = getSpacingValue(data.spacing); return ` ${escapeHtml(data.name)} - Resume
${data.includePhoto && data.photo ? `${escapeHtml(data.name)}` : ""}

${escapeHtml(data.name)}

${data.title ? `
${escapeHtml(data.title)}
` : ""}
${data.email ? `${escapeHtml(data.email)}` : ""} ${data.phone ? `📞 ${escapeHtml(data.phone)}` : ""} ${data.location ? `📍 ${escapeHtml(data.location)}` : ""} ${data.website ? `🌐 ${escapeHtml(data.website)}` : ""} ${data.linkedin ? `💼 LinkedIn` : ""} ${data.github ? `💻 GitHub` : ""}
${data.summary ? `

Professional Summary

${escapeHtml(data.summary)}

` : ""} ${data.experience.length > 0 ? `

Experience

${data.experience.map(exp => `
${escapeHtml(exp.title)}
${escapeHtml(exp.company)}
${escapeHtml(exp.description)}
`).join("")}
` : ""} ${data.education.length > 0 ? `

Education

${data.education.map(edu => `
${escapeHtml(edu.degree)}
${escapeHtml(edu.school)}
${edu.details ? `
${escapeHtml(edu.details)}
` : ""}
`).join("")}
` : ""} ${data.skills.length > 0 ? `

Skills

${data.skills.map(skill => `
${escapeHtml(skill.name)}
${Array.from({ length: 5 }, (_, i) => `
`).join("")}
`).join("")}
` : ""} ${data.projects.length > 0 ? `

Projects

${data.projects.map(project => `
${escapeHtml(project.name)}
${project.url ? `${escapeHtml(project.url)}` : ""}
${escapeHtml(project.description)}
`).join("")}
` : ""} ${data.certifications.length > 0 ? `

Certifications

${data.certifications.map(cert => `
${escapeHtml(cert.name)}
${escapeHtml(cert.year)}${cert.issuer ? ` • ${escapeHtml(cert.issuer)}` : ""}
`).join("")}
` : ""} ${data.languages.length > 0 ? `

Languages

${data.languages.map(lang => `
${escapeHtml(lang.name)}
${escapeHtml(lang.proficiency)}
`).join("")}
` : ""}
`; } // Generate cover letter HTML export function generateCoverLetterHTML(data: CoverLetterData): string { const today = new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", }); return ` Cover Letter - ${escapeHtml(data.name)}
${escapeHtml(data.name)}
${escapeHtml(data.email) || ""} ${data.phone ? `• ${escapeHtml(data.phone)}` : ""} ${data.location ? `• ${escapeHtml(data.location)}` : ""}
${today}
Hiring Manager
${escapeHtml(data.position)}
${escapeHtml(data.company)}
${escapeHtml(data.content)}

Sincerely,

${escapeHtml(data.name)}

`; } // Generate markdown resume export function generateMarkdown(data: ResumeData): string { let md = `# ${data.name}\n\n`; if (data.title) md += `**${data.title}**\n\n`; const contact = [ data.email && `📧 ${data.email}`, data.phone && `📞 ${data.phone}`, data.location && `📍 ${data.location}`, data.website && `🌐 ${data.website}`, data.linkedin && `💼 ${data.linkedin}`, data.github && `💻 ${data.github}`, ].filter(Boolean); if (contact.length > 0) md += `${contact.join(" • ")}\n\n`; if (data.summary) md += `## Professional Summary\n\n${data.summary}\n\n`; if (data.experience.length > 0) { md += `## Experience\n\n`; data.experience.forEach((exp) => { md += `### ${exp.title}\n**${exp.company}** • ${exp.dates}\n\n${exp.description}\n\n`; }); } if (data.education.length > 0) { md += `## Education\n\n`; data.education.forEach((edu) => { md += `### ${edu.degree}\n**${edu.school}** • ${edu.dates}\n`; if (edu.details) md += `\n${edu.details}\n`; md += `\n`; }); } if (data.skills.length > 0) { md += `## Skills\n\n`; data.skills.forEach((skill) => { const level = "●".repeat(skill.level) + "○".repeat(5 - skill.level); md += `- **${skill.name}**: ${level}\n`; }); md += `\n`; } if (data.projects.length > 0) { md += `## Projects\n\n`; data.projects.forEach((project) => { md += `### ${project.name}\n${project.description}`; if (project.url) md += `\n\n${project.url}`; md += `\n\n`; }); } if (data.certifications.length > 0) { md += `## Certifications\n\n`; data.certifications.forEach((cert) => { md += `- **${cert.name}** (${cert.year})`; if (cert.issuer) md += ` - ${cert.issuer}`; md += `\n`; }); md += `\n`; } if (data.languages.length > 0) { md += `## Languages\n\n`; data.languages.forEach((lang) => { md += `- **${lang.name}**: ${lang.proficiency}\n`; }); } return md; } // Helper functions for styles function getTemplateStyles(template: string) { const templates: Record = { modern: { header: "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;" }, classic: { header: "background: #2c3e50; color: white;" }, minimal: { header: "background: white; color: #333; border-bottom: 1px solid #e5e5e5;" }, creative: { header: "background: linear-gradient(45deg, #ff6b6b, #feca57); color: white;" }, executive: { header: "background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); color: white;" }, technical: { header: "background: #1a1a1a; color: #00ff00; font-family: 'Courier New', monospace;" }, }; return templates[template] || templates.modern; } function getLayoutStyles(layout: string) { const layouts: Record = { "single-column": { container: "padding: 40px 60px;", headerAlign: "center", contactLayout: "flex-wrap: wrap; justify-content: center;", body: "", }, "two-column": { container: "display: grid; grid-template-columns: 250px 1fr;", headerAlign: "left", contactLayout: "flex-direction: column; align-items: flex-start;", body: "grid-column: 2;", sidebar: "grid-column: 1; grid-row: 1 / span 2;", }, sidebar: { container: "display: flex;", headerAlign: "left", contactLayout: "flex-direction: column;", body: "flex: 1;", sidebar: "width: 200px; background: #f8f9fa;", }, }; return layouts[layout] || layouts["single-column"]; } function getFontFamily(font: string): string { const fonts: Record = { inter: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif", roboto: "'Roboto', sans-serif", lato: "'Lato', sans-serif", "open-sans": "'Open Sans', sans-serif", poppins: "'Poppins', sans-serif", }; return fonts[font] || fonts.inter; } function getFontSizes(size: string) { const sizes: Record = { small: { name: "28px", title: "16px", contact: "12px", sectionTitle: "16px", entryTitle: "15px", body: "13px", small: "11px" }, medium: { name: "32px", title: "18px", contact: "14px", sectionTitle: "18px", entryTitle: "16px", body: "14px", small: "12px" }, large: { name: "36px", title: "20px", contact: "15px", sectionTitle: "20px", entryTitle: "17px", body: "15px", small: "13px" }, }; return sizes[size] || sizes.medium; } function getSpacingValue(spacing: string): number { const values: Record = { compact: 15, normal: 25, spacious: 35 }; return values[spacing] || values.normal; } // Main function