resuml 1.13.1 → 1.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ats/i18n/en.ts","../src/ats/i18n/de.ts","../src/ats/i18n/index.ts","../src/ats/genericChecks.ts","../src/ats/jdMatcher.ts","../src/ats/scoring.ts","../src/ats/index.ts","../src/utils/resumeTemplate.ts","../src/utils/themeInfo.ts"],"sourcesContent":["export interface LanguageData {\n actionVerbs: string[];\n pronouns: string[];\n stopWords: string[];\n}\n\nconst en: LanguageData = {\n actionVerbs: [\n // Leadership & Management\n 'achieved', 'administered', 'advanced', 'allocated', 'approved', 'assigned',\n 'authorized', 'chaired', 'consolidated', 'coordinated', 'delegated', 'directed',\n 'established', 'executed', 'headed', 'hired', 'hosted', 'led', 'managed',\n 'mentored', 'motivated', 'orchestrated', 'organized', 'oversaw', 'planned',\n 'presided', 'prioritized', 'produced', 'recruited', 'spearheaded', 'supervised',\n // Technical & Engineering\n 'architected', 'automated', 'built', 'coded', 'configured', 'debugged',\n 'deployed', 'designed', 'developed', 'devised', 'engineered', 'implemented',\n 'installed', 'integrated', 'launched', 'maintained', 'migrated', 'modernized',\n 'optimized', 'overhauled', 'programmed', 'prototyped', 'refactored',\n 'reengineered', 'resolved', 'restructured', 'revamped', 'scaled',\n 'standardized', 'streamlined', 'tested', 'troubleshot', 'upgraded',\n // Achievement & Impact\n 'accelerated', 'accomplished', 'boosted', 'completed', 'contributed',\n 'converted', 'decreased', 'delivered', 'doubled', 'earned', 'eliminated',\n 'exceeded', 'expanded', 'expedited', 'generated', 'grew', 'improved',\n 'increased', 'maximized', 'minimized', 'outperformed', 'pioneered',\n 'recovered', 'reduced', 'saved', 'simplified', 'solved', 'surpassed',\n 'transformed', 'tripled',\n // Communication & Collaboration\n 'advised', 'advocated', 'briefed', 'collaborated', 'communicated',\n 'consulted', 'convinced', 'counseled', 'defined', 'demonstrated',\n 'documented', 'educated', 'facilitated', 'guided', 'influenced',\n 'informed', 'instructed', 'liaised', 'negotiated', 'partnered',\n 'persuaded', 'presented', 'promoted', 'proposed', 'published',\n 'recommended', 'represented', 'trained',\n // Analysis & Research\n 'analyzed', 'assessed', 'audited', 'benchmarked', 'calculated',\n 'compared', 'compiled', 'conducted', 'discovered', 'evaluated',\n 'examined', 'explored', 'forecasted', 'identified', 'inspected',\n 'interpreted', 'investigated', 'mapped', 'measured', 'modeled',\n 'monitored', 'quantified', 'researched', 'reviewed', 'surveyed',\n 'synthesized', 'tracked', 'validated', 'verified',\n // Creation & Innovation\n 'conceptualized', 'crafted', 'created', 'customized', 'formulated',\n 'founded', 'initiated', 'innovated', 'introduced', 'invented',\n 'originated', 'shaped',\n ],\n pronouns: ['i', 'me', 'my', 'mine', 'myself', 'we', 'our', 'ours'],\n stopWords: [\n // Articles & determiners\n 'a', 'an', 'the', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',\n 'of', 'with', 'by', 'from', 'is', 'was', 'are', 'were', 'be', 'been',\n 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would',\n 'could', 'should', 'may', 'might', 'shall', 'can', 'this', 'that',\n 'these', 'those', 'it', 'its', 'as', 'if', 'not', 'no', 'so', 'up',\n 'out', 'about', 'into', 'over', 'after', 'before', 'between', 'under',\n 'above', 'below', 'all', 'each', 'every', 'both', 'few', 'more',\n 'most', 'other', 'some', 'such', 'than', 'too', 'very',\n // Pronouns & possessives (also checked by pronoun check, but filter from JD keywords)\n 'you', 'your', 'yours', 'yourself', 'we', 'our', 'ours', 'ourselves',\n 'they', 'them', 'their', 'theirs', 'he', 'she', 'his', 'her', 'hers',\n 'who', 'whom', 'whose', 'which', 'what', 'where', 'when', 'how', 'why',\n // Common JD filler words (not meaningful for skill matching)\n 'able', 'also', 'across', 'already', 'always', 'among', 'any', 'apply',\n 'become', 'believe', 'best', 'bring', 'change', 'come', 'committed',\n 'company', 'comfortable', 'critical', 'current', 'day', 'desired',\n 'either', 'end', 'ensure', 'environment', 'equal', 'even', 'excellent',\n 'exciting', 'exceptional', 'expected', 'experience', 'fast', 'field',\n 'find', 'first',\n 'focused', 'follow', 'get', 'give', 'go', 'going', 'good', 'great',\n 'group', 'grow', 'growing', 'growth', 'help', 'here', 'high', 'highly',\n 'ideal', 'impact', 'important', 'include', 'includes', 'including',\n 'industry', 'interested', 'job', 'join', 'just', 'keep', 'key', 'know',\n 'large', 'latest', 'lead', 'level', 'like', 'location', 'long', 'look',\n 'looking', 'love', 'make', 'many', 'much', 'must', 'need', 'new',\n 'next', 'offer', 'one', 'only', 'open', 'opportunity', 'order',\n 'others', 'own', 'pace', 'part', 'partner', 'passionate', 'people',\n 'per', 'play', 'plus', 'position', 'preferred', 'provide', 'put',\n 'qualifications', 'quickly', 'range', 'related', 'required',\n 'requirements', 'requirement', 'responsible', 'responsibilities',\n 'responsibility', 'result', 'right', 'role', 'run',\n 'same', 'see', 'seek', 'seeking', 'set', 'several', 'since',\n 'skills', 'someone', 'start', 'state', 'still', 'strong', 'success',\n 'successful', 'support', 'sure', 'take', 'team', 'then', 'there',\n 'thing', 'think', 'through', 'time', 'together', 'top', 'truly',\n 'try', 'two', 'type', 'use', 'used', 'using', 'value', 'want',\n 'way', 'well', 'while', 'within', 'without', 'work', 'working',\n 'world', 'would', 'year', 'years',\n // Section headers & structural words (not technical skills)\n 'description', 'overview', 'summary', 'duties', 'bachelor', 'bachelors',\n 'master', 'masters', 'degree', 'phd', 'minimum', 'preferred',\n 'implement', 'process', 'robust', 'consistent', 'operations',\n // URL/email/domain fragments\n 'http', 'https', 'www', 'com', 'org', 'net', 'mailto',\n // Resume/YAML schema field names (in case raw YAML is pasted)\n 'name', 'keywords', 'highlights', 'startdate', 'enddate', 'website',\n 'profiles', 'basics', 'position', 'institution', 'studytype',\n 'fluency', 'issuer', 'network', 'username', 'countrycode', 'region',\n // Generic nouns that aren't skills\n 'product', 'company', 'service', 'services', 'platform', 'solutions',\n 'ability', 'opportunity', 'candidate', 'applicant', 'position',\n 'salary', 'compensation', 'benefits', 'perks', 'bonus',\n 'development', 'management', 'knowledge', 'modern', 'advanced',\n 'practices', 'nice', 'technologies', 'technology', 'frameworks',\n 'framework', 'tools', 'data', 'based', 'contribute', 'contributions',\n 'migration', 'leading', 'source', 'visit',\n // Common verbs & verb forms (not technical skills, supplement action verbs list)\n 'collaborate', 'collaborating', 'collaboratively', 'communicate',\n 'communicating', 'contributing', 'coordinate', 'coordinating',\n 'demonstrate', 'demonstrating', 'design', 'designing', 'designed',\n 'develop', 'developing', 'developed', 'drive', 'driving', 'driven',\n 'enable', 'enabling', 'evaluate', 'evaluating', 'execute', 'executing',\n 'facilitate', 'facilitating', 'identify', 'identifying', 'influence',\n 'influencing', 'interact', 'interacting', 'lead', 'leverage',\n 'leveraging', 'manage', 'managing', 'mentor', 'mentoring', 'operate',\n 'operating', 'optimize', 'optimizing', 'participate', 'participating',\n 'report', 'reporting', 'solve', 'solving', 'understand', 'understanding',\n // Common adjectives & descriptors (not technical skills)\n 'fluent', 'proficient', 'deep', 'solid', 'proven', 'hands-on',\n 'detail-oriented', 'results-driven', 'self-motivated', 'proactive',\n 'creative', 'innovative', 'dynamic', 'strategic', 'analytical',\n 'collaborative', 'effective', 'efficient', 'reliable', 'flexible',\n 'adaptable', 'motivated', 'dedicated', 'capable', 'qualified',\n 'diverse', 'inclusive', 'global', 'local', 'remote', 'hybrid',\n 'onsite', 'full-time', 'part-time', 'contract', 'permanent',\n // Role titles & department names (not skills themselves)\n 'designer', 'designers', 'developer', 'developers', 'engineer',\n 'engineers', 'manager', 'managers', 'director', 'analyst', 'analysts',\n 'architect', 'architects', 'consultant', 'consultants', 'specialist',\n 'specialists', 'coordinator', 'lead', 'principal', 'staff', 'junior',\n 'mid', 'department', 'organization', 'division', 'stakeholder',\n 'stakeholders', 'client', 'clients', 'customer', 'customers',\n // Date & time words\n 'date', 'dates', 'month', 'months', 'week', 'weeks', 'daily',\n 'weekly', 'monthly', 'quarterly', 'annual', 'annually',\n // More generic words that aren't skills\n 'code', 'coding', 'url', 'contact', 'information', 'apply', 'application',\n 'review', 'reviews', 'quality', 'scale', 'scalable', 'system', 'systems',\n 'solution', 'feature', 'features', 'project', 'projects', 'build',\n 'building', 'deliver', 'delivery', 'cross-functional',\n ],\n};\n\nexport default en;\n","import type { LanguageData } from './en';\n\nconst de: LanguageData = {\n actionVerbs: [\n // Führung & Management\n 'geleitet', 'geführt', 'koordiniert', 'organisiert', 'verwaltet',\n 'delegiert', 'beaufsichtigt', 'betreut', 'eingestellt', 'motiviert',\n 'verantwortet', 'gesteuert', 'überwacht', 'priorisiert', 'geplant',\n // Technik & Entwicklung\n 'entwickelt', 'implementiert', 'programmiert', 'konfiguriert', 'automatisiert',\n 'deployt', 'gebaut', 'entworfen', 'integriert', 'migriert', 'modernisiert',\n 'optimiert', 'refaktoriert', 'skaliert', 'standardisiert', 'getestet',\n 'aufgebaut', 'eingeführt', 'bereitgestellt', 'umgesetzt',\n // Leistung & Ergebnisse\n 'verbessert', 'gesteigert', 'reduziert', 'beschleunigt', 'erreicht',\n 'übertroffen', 'erweitert', 'vereinfacht', 'gelöst', 'transformiert',\n 'erhöht', 'verdoppelt', 'verdreifacht', 'generiert', 'gespart',\n 'maximiert', 'minimiert', 'eliminiert', 'geliefert', 'abgeschlossen',\n // Kommunikation & Zusammenarbeit\n 'beraten', 'präsentiert', 'dokumentiert', 'geschult', 'trainiert',\n 'vermittelt', 'kommuniziert', 'verhandelt', 'zusammengearbeitet',\n 'unterstützt', 'gefördert', 'empfohlen', 'vorgestellt', 'publiziert',\n // Analyse & Forschung\n 'analysiert', 'bewertet', 'evaluiert', 'untersucht', 'erforscht',\n 'identifiziert', 'gemessen', 'überwacht', 'validiert', 'verifiziert',\n 'geprüft', 'verglichen', 'recherchiert', 'quantifiziert',\n // Kreation & Innovation\n 'konzipiert', 'erstellt', 'gestaltet', 'initiiert', 'innoviert',\n 'eingeführt', 'gegründet', 'formuliert',\n ],\n pronouns: ['ich', 'mich', 'mir', 'mein', 'meine', 'meinem', 'meiner', 'meines', 'wir', 'unser', 'unsere'],\n stopWords: [\n 'ein', 'eine', 'einer', 'eines', 'einem', 'der', 'die', 'das', 'den',\n 'dem', 'des', 'und', 'oder', 'aber', 'in', 'an', 'auf', 'zu', 'für',\n 'von', 'mit', 'bei', 'aus', 'ist', 'war', 'sind', 'waren', 'wird',\n 'wurde', 'werden', 'hat', 'hatte', 'haben', 'hatten', 'sein', 'kann',\n 'könnte', 'soll', 'sollte', 'muss', 'musste', 'darf', 'diese',\n 'dieser', 'dieses', 'diesem', 'diesen', 'als', 'wenn', 'nicht',\n 'kein', 'keine', 'so', 'auch', 'noch', 'schon', 'nach', 'vor',\n 'über', 'unter', 'zwischen', 'durch', 'ohne', 'um', 'bis',\n 'alle', 'jede', 'jeder', 'jedes', 'mehr', 'viel', 'sehr',\n ],\n};\n\nexport default de;\n","import en from './en';\nimport de from './de';\nimport type { LanguageData } from './en';\n\nexport type { LanguageData };\n\nconst languages: Record<string, LanguageData> = { en, de };\n\nexport function getLanguageData(language: string): LanguageData {\n return languages[language] ?? languages['en'] ?? en;\n}\n","import type { ResumeSchema } from '../types/resume';\nimport type { AtsCheck } from './types';\nimport { getLanguageData } from './i18n/index';\n\ntype CheckFn = (resume: ResumeSchema, language: string) => AtsCheck;\n\nfunction wordCount(text: string): number {\n return text.trim().split(/\\s+/).filter(Boolean).length;\n}\n\nfunction getFirstWord(text: string): string {\n return text.trim().split(/\\s+/)[0]?.toLowerCase().replace(/[^a-zA-ZäöüßÄÖÜàáâãéèêëíìîïóòôõúùûüñç]/g, '') || '';\n}\n\nconst contactComplete: CheckFn = (resume) => {\n const b = resume.basics;\n const hasName = !!b?.name;\n const hasEmail = !!b?.email;\n const hasPhone = !!b?.phone;\n const hasCity = !!b?.location?.city;\n const fields = [hasName, hasEmail, hasPhone, hasCity];\n const presentCount = fields.filter(Boolean).length;\n const passed = presentCount === fields.length;\n const missing: string[] = [];\n if (!hasName) missing.push('name');\n if (!hasEmail) missing.push('email');\n if (!hasPhone) missing.push('phone');\n if (!hasCity) missing.push('location.city');\n\n return {\n id: 'contact-complete',\n category: 'contact',\n weight: 'high',\n passed,\n score: Math.round((presentCount / fields.length) * 100),\n message: passed\n ? 'Contact information is complete.'\n : `Missing contact fields: ${missing.join(', ')}.`,\n suggestion: passed ? undefined : `Add the following to your basics section: ${missing.join(', ')}.`,\n };\n};\n\nconst hasSummary: CheckFn = (resume) => {\n const summary = resume.basics?.summary?.trim();\n if (!summary) {\n return {\n id: 'has-summary',\n category: 'content',\n weight: 'high',\n passed: false,\n score: 0,\n message: 'No professional summary found.',\n suggestion: 'Add a 2-4 sentence professional summary to your basics section highlighting your experience and key skills.',\n };\n }\n const words = wordCount(summary);\n const tooShort = words < 15;\n const tooLong = words > 100;\n const passed = !tooShort && !tooLong;\n let score = 100;\n if (tooShort) score = Math.round((words / 15) * 60);\n if (tooLong) score = Math.max(60, 100 - (words - 100));\n\n return {\n id: 'has-summary',\n category: 'content',\n weight: 'high',\n passed,\n score,\n message: tooShort\n ? `Summary is too short (${words} words). Aim for 15-100 words.`\n : tooLong\n ? `Summary is too long (${words} words). Aim for 15-100 words.`\n : `Summary length is good (${words} words).`,\n suggestion: tooShort\n ? 'Expand your summary to describe your experience, expertise, and career goals in 15-100 words.'\n : tooLong\n ? 'Shorten your summary to the most impactful 15-100 words. Focus on key achievements and expertise.'\n : undefined,\n };\n};\n\nconst hasLinkedin: CheckFn = (resume) => {\n const profiles = resume.basics?.profiles || [];\n const linkedin = profiles.find(\n (p) => p.network?.toLowerCase() === 'linkedin' || p.url?.toLowerCase().includes('linkedin.com')\n );\n return {\n id: 'has-linkedin',\n category: 'contact',\n weight: 'medium',\n passed: !!linkedin,\n score: linkedin ? 100 : 0,\n message: linkedin ? 'LinkedIn profile found.' : 'No LinkedIn profile found.',\n suggestion: linkedin ? undefined : 'Add a LinkedIn profile to your basics.profiles section.',\n };\n};\n\nconst workHighlights: CheckFn = (resume) => {\n const work = resume.work || [];\n if (work.length === 0) {\n return {\n id: 'work-highlights',\n category: 'content',\n weight: 'high',\n passed: false,\n score: 0,\n message: 'No work experience entries found.',\n suggestion: 'Add work experience entries with highlights describing your accomplishments.',\n };\n }\n const minHighlights = 2;\n const entriesWithEnough = work.filter((w) => (w.highlights?.length || 0) >= minHighlights);\n const passed = entriesWithEnough.length === work.length;\n const score = Math.round((entriesWithEnough.length / work.length) * 100);\n const lacking = work\n .filter((w) => (w.highlights?.length || 0) < minHighlights)\n .map((w) => `\"${w.position || 'Unknown'} at ${w.name || 'Unknown'}\" (${w.highlights?.length || 0} highlights)`);\n\n return {\n id: 'work-highlights',\n category: 'content',\n weight: 'high',\n passed,\n score,\n message: passed\n ? 'All work entries have sufficient highlights.'\n : `Some work entries need more highlights: ${lacking.join('; ')}.`,\n suggestion: passed\n ? undefined\n : `Add at least ${minHighlights} bullet-point highlights to each work entry describing specific accomplishments.`,\n };\n};\n\nconst actionVerbs: CheckFn = (resume, language) => {\n const langData = getLanguageData(language);\n const verbs = new Set(langData.actionVerbs);\n const allHighlights: { text: string; source: string }[] = [];\n\n for (const w of resume.work || []) {\n for (const h of w.highlights || []) {\n allHighlights.push({ text: h, source: `${w.position || ''} at ${w.name || ''}` });\n }\n }\n for (const p of resume.projects || []) {\n for (const h of p.highlights || []) {\n allHighlights.push({ text: h, source: `project \"${p.name || ''}\"` });\n }\n }\n for (const v of resume.volunteer || []) {\n for (const h of v.highlights || []) {\n allHighlights.push({ text: h, source: `volunteer at ${v.organization || ''}` });\n }\n }\n\n if (allHighlights.length === 0) {\n return {\n id: 'action-verbs',\n category: 'content',\n weight: 'high',\n passed: false,\n score: 0,\n message: 'No highlights found to check for action verbs.',\n suggestion: 'Add highlights to your work, project, or volunteer entries starting with strong action verbs.',\n };\n }\n\n const withActionVerb = allHighlights.filter((h) => verbs.has(getFirstWord(h.text)));\n const withoutActionVerb = allHighlights.filter((h) => !verbs.has(getFirstWord(h.text)));\n const passed = withoutActionVerb.length === 0;\n const score = Math.round((withActionVerb.length / allHighlights.length) * 100);\n\n const examples = withoutActionVerb.slice(0, 3).map(\n (h) => `\"${h.text.substring(0, 60)}${h.text.length > 60 ? '...' : ''}\" (${h.source})`\n );\n\n return {\n id: 'action-verbs',\n category: 'content',\n weight: 'high',\n passed,\n score,\n message: passed\n ? 'All highlights start with action verbs.'\n : `${withoutActionVerb.length} of ${allHighlights.length} highlights don't start with an action verb.`,\n suggestion: passed\n ? undefined\n : `Start each highlight with a strong action verb (e.g., \"Developed\", \"Implemented\", \"Led\"). Fix: ${examples.join('; ')}.`,\n };\n};\n\nconst quantifiedImpact: CheckFn = (resume) => {\n const quantPattern = /\\d+%?|\\$[\\d,]+|[\\d,]+\\+?\\s*(users|clients|customers|people|team|members|projects|applications|servers|services|endpoints|requests|transactions)/i;\n const allHighlights: string[] = [];\n\n for (const w of resume.work || []) {\n allHighlights.push(...(w.highlights || []));\n }\n for (const p of resume.projects || []) {\n allHighlights.push(...(p.highlights || []));\n }\n\n if (allHighlights.length === 0) {\n return {\n id: 'quantified-impact',\n category: 'content',\n weight: 'medium',\n passed: false,\n score: 0,\n message: 'No highlights found to check for quantified impact.',\n suggestion: 'Add measurable results to your highlights (e.g., \"Reduced load time by 40%\", \"Managed team of 8\").',\n };\n }\n\n const quantified = allHighlights.filter((h) => quantPattern.test(h));\n const ratio = quantified.length / allHighlights.length;\n // At least 50% of highlights should have numbers\n const passed = ratio >= 0.5;\n const score = Math.min(100, Math.round(ratio * 200)); // 50% = 100 score\n\n return {\n id: 'quantified-impact',\n category: 'content',\n weight: 'medium',\n passed,\n score,\n message: passed\n ? `${quantified.length} of ${allHighlights.length} highlights include quantified results.`\n : `Only ${quantified.length} of ${allHighlights.length} highlights include numbers or metrics.`,\n suggestion: passed\n ? undefined\n : 'Add specific numbers, percentages, or metrics to your highlights (e.g., \"Improved performance by 30%\", \"Managed $2M budget\").',\n };\n};\n\nconst dateConsistency: CheckFn = (resume) => {\n const work = resume.work || [];\n if (work.length < 2) {\n return {\n id: 'date-consistency',\n category: 'structure',\n weight: 'medium',\n passed: true,\n score: 100,\n message: 'Date consistency check passed (fewer than 2 work entries).',\n };\n }\n\n const issues: string[] = [];\n\n // Check that each entry has a startDate\n for (const w of work) {\n if (!w.startDate) {\n issues.push(`\"${w.position || 'Unknown'} at ${w.name || 'Unknown'}\" is missing a start date.`);\n }\n }\n\n // Check for gaps > 6 months between consecutive jobs\n const sorted = [...work]\n .filter((w): w is typeof w & { startDate: string } => Boolean(w.startDate))\n .sort((a, b) => (a.startDate > b.startDate ? 1 : -1));\n\n for (let i = 0; i < sorted.length - 1; i++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const current = sorted[i]!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const next = sorted[i + 1]!;\n const endDate = current.endDate ?? current.startDate;\n const gapMs = new Date(next.startDate).getTime() - new Date(endDate).getTime();\n const gapMonths = gapMs / (1000 * 60 * 60 * 24 * 30);\n\n if (gapMonths > 6) {\n issues.push(\n `Gap of ~${Math.round(gapMonths)} months between \"${current.name ?? 'Unknown'}\" (ended ${endDate}) and \"${next.name ?? 'Unknown'}\" (started ${next.startDate}).`\n );\n }\n }\n\n const passed = issues.length === 0;\n return {\n id: 'date-consistency',\n category: 'structure',\n weight: 'medium',\n passed,\n score: passed ? 100 : Math.max(0, 100 - issues.length * 25),\n message: passed\n ? 'Work experience dates are consistent with no major gaps.'\n : `Date issues found: ${issues.join(' ')}`,\n suggestion: passed\n ? undefined\n : 'Ensure all work entries have start dates. If there are employment gaps, consider adding freelance, volunteer, or education entries to fill them.',\n };\n};\n\nconst skillsPopulated: CheckFn = (resume) => {\n const skills = resume.skills || [];\n const minCategories = 3;\n const categoriesWithKeywords = skills.filter((s) => s.keywords && s.keywords.length > 0);\n const passed = categoriesWithKeywords.length >= minCategories;\n const score = Math.min(100, Math.round((categoriesWithKeywords.length / minCategories) * 100));\n\n return {\n id: 'skills-populated',\n category: 'structure',\n weight: 'medium',\n passed,\n score,\n message: passed\n ? `${categoriesWithKeywords.length} skill categories with keywords found.`\n : `Only ${categoriesWithKeywords.length} skill categories with keywords found (need at least ${minCategories}).`,\n suggestion: passed\n ? undefined\n : `Add at least ${minCategories} skill categories with specific keywords (e.g., \"Languages: TypeScript, Python\", \"Frameworks: React, Node.js\").`,\n };\n};\n\nconst educationComplete: CheckFn = (resume) => {\n const education = resume.education || [];\n if (education.length === 0) {\n return {\n id: 'education-complete',\n category: 'structure',\n weight: 'low',\n passed: false,\n score: 0,\n message: 'No education entries found.',\n suggestion: 'Add at least one education entry with institution, area, and studyType.',\n };\n }\n\n const complete = education.filter((e) => e.institution && e.area && e.studyType);\n const passed = complete.length === education.length;\n const score = Math.round((complete.length / education.length) * 100);\n const incomplete = education\n .filter((e) => !e.institution || !e.area || !e.studyType)\n .map((e) => {\n const missing: string[] = [];\n if (!e.institution) missing.push('institution');\n if (!e.area) missing.push('area');\n if (!e.studyType) missing.push('studyType');\n return `\"${e.institution || 'Unknown'}\" missing: ${missing.join(', ')}`;\n });\n\n return {\n id: 'education-complete',\n category: 'structure',\n weight: 'low',\n passed,\n score,\n message: passed\n ? 'All education entries are complete.'\n : `Incomplete education entries: ${incomplete.join('; ')}.`,\n suggestion: passed\n ? undefined\n : 'Ensure each education entry has institution, area (field of study), and studyType (degree type).',\n };\n};\n\nconst noPronouns: CheckFn = (resume, language) => {\n const langData = getLanguageData(language);\n const pronounSet = new Set(langData.pronouns);\n\n const textBlocks: { text: string; source: string }[] = [];\n\n if (resume.basics?.summary) {\n textBlocks.push({ text: resume.basics.summary, source: 'summary' });\n }\n for (const w of resume.work || []) {\n if (w.summary) textBlocks.push({ text: w.summary, source: `work summary (${w.name || 'Unknown'})` });\n for (const h of w.highlights || []) {\n textBlocks.push({ text: h, source: `work highlight (${w.name || 'Unknown'})` });\n }\n }\n for (const p of resume.projects || []) {\n if (p.description) textBlocks.push({ text: p.description, source: `project (${p.name || 'Unknown'})` });\n for (const h of p.highlights || []) {\n textBlocks.push({ text: h, source: `project highlight (${p.name || 'Unknown'})` });\n }\n }\n\n const found: { pronoun: string; source: string }[] = [];\n for (const block of textBlocks) {\n const words = block.text.toLowerCase().split(/\\s+/);\n for (const word of words) {\n const clean = word.replace(/[^a-zA-ZäöüßÄÖÜ]/g, '');\n if (pronounSet.has(clean)) {\n found.push({ pronoun: clean, source: block.source });\n }\n }\n }\n\n const passed = found.length === 0;\n const uniquePronouns = [...new Set(found.map((f) => f.pronoun))];\n const examples = found.slice(0, 3).map((f) => `\"${f.pronoun}\" in ${f.source}`);\n\n return {\n id: 'no-pronouns',\n category: 'content',\n weight: 'medium',\n passed,\n score: passed ? 100 : Math.max(0, 100 - found.length * 15),\n message: passed\n ? 'No first-person pronouns found in resume content.'\n : `Found ${found.length} first-person pronoun(s): ${uniquePronouns.join(', ')}.`,\n suggestion: passed\n ? undefined\n : `Remove first-person pronouns from your resume. Instead of \"I managed a team\", write \"Managed a team\". Found: ${examples.join('; ')}.`,\n };\n};\n\nconst sectionCompleteness: CheckFn = (resume) => {\n const required = ['basics', 'work', 'education', 'skills'] as const;\n const present = required.filter((section) => {\n const value = resume[section];\n if (Array.isArray(value)) return value.length > 0;\n return value !== undefined;\n });\n const missing = required.filter((s) => !present.includes(s));\n const passed = missing.length === 0;\n\n return {\n id: 'section-completeness',\n category: 'structure',\n weight: 'low',\n passed,\n score: Math.round((present.length / required.length) * 100),\n message: passed\n ? 'All essential resume sections are present.'\n : `Missing essential sections: ${missing.join(', ')}.`,\n suggestion: passed ? undefined : `Add the following sections to your resume: ${missing.join(', ')}.`,\n };\n};\n\nexport const allChecks: CheckFn[] = [\n contactComplete,\n hasSummary,\n hasLinkedin,\n workHighlights,\n actionVerbs,\n quantifiedImpact,\n dateConsistency,\n skillsPopulated,\n educationComplete,\n noPronouns,\n sectionCompleteness,\n];\n\nexport function runGenericChecks(resume: ResumeSchema, language: string): AtsCheck[] {\n return allChecks.map((check) => check(resume, language));\n}\n","import type { ResumeSchema } from '../types/resume';\nimport type { AtsKeywordMatch } from './types';\nimport { getLanguageData } from './i18n/index';\n\n/**\n * Pre-process text to remove URLs, email addresses, and other non-content noise.\n */\nfunction stripNoise(text: string): string {\n return text\n // Remove URLs (http(s)://..., www.xxx.com, etc.)\n .replace(/https?:\\/\\/[^\\s]+/gi, ' ')\n .replace(/www\\.[^\\s]+/gi, ' ')\n // Remove email addresses\n .replace(/[\\w.+-]+@[\\w.-]+\\.[a-z]{2,}/gi, ' ')\n // Remove standalone paths/slugs (e.g. /path/to/thing)\n .replace(/(?:^|\\s)\\/[\\w/.-]+/g, ' ')\n // Remove camelCase schema-like identifiers (e.g. startDate, endDate)\n .replace(/\\b[a-z]+[A-Z][a-zA-Z]*\\b/g, (match) => {\n // Split camelCase into separate words\n return match.replace(/([a-z])([A-Z])/g, '$1 $2');\n });\n}\n\n/**\n * Tokenize text into normalized words, removing stop words and short tokens.\n */\nfunction tokenize(text: string, stopWords: Set<string>): string[] {\n return text\n .toLowerCase()\n .replace(/[^a-zA-Z0-9äöüßÄÖÜàáâãéèêëíìîïóòôõúùûüñç\\s/+-]/g, ' ')\n .split(/\\s+/)\n .filter((word) => {\n if (word.length <= 2) return false;\n if (stopWords.has(word)) return false;\n // Filter URL fragments and domain-like tokens\n if (word.startsWith('//') || word.startsWith('http')) return false;\n if (/^\\d+$/.test(word)) return false; // pure numbers\n if (/^[/+-]+$/.test(word)) return false; // pure punctuation\n return true;\n });\n}\n\n/**\n * Simple stemmer: strips common suffixes for rough normalization.\n * This avoids the heavy `natural` dependency while still providing useful matching.\n */\nfunction simpleStem(word: string, language: string): string {\n if (language === 'de') {\n return word\n .replace(/(ung|heit|keit|schaft|lich|isch|iert|ieren|tion|ment)$/, '')\n .replace(/(en|er|es|em|te|st)$/, '');\n }\n // English\n return word\n .replace(/(ment|ness|tion|sion|ance|ence|ity|ing|ous|ive|able|ible|ful|less)$/, '')\n .replace(/(ies)$/, 'y')\n .replace(/(es|ed|s)$/, '');\n}\n\n/**\n * Extract all text content from a resume.\n */\nfunction extractResumeText(resume: ResumeSchema): string {\n const parts: string[] = [];\n\n if (resume.basics?.summary) parts.push(resume.basics.summary);\n if (resume.basics?.label) parts.push(resume.basics.label);\n\n for (const w of resume.work || []) {\n if (w.position) parts.push(w.position);\n if (w.summary) parts.push(w.summary);\n parts.push(...(w.highlights || []));\n }\n for (const s of resume.skills || []) {\n if (s.name) parts.push(s.name);\n parts.push(...(s.keywords || []));\n }\n for (const p of resume.projects || []) {\n if (p.name) parts.push(p.name);\n if (p.description) parts.push(p.description);\n parts.push(...(p.highlights || []));\n }\n for (const e of resume.education || []) {\n if (e.area) parts.push(e.area);\n if (e.studyType) parts.push(e.studyType);\n parts.push(...(e.courses || []));\n }\n for (const c of resume.certificates || []) {\n if (c.name) parts.push(c.name);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Build a TF (term frequency) map from tokenized text.\n */\nfunction buildTfMap(tokens: string[]): Map<string, number> {\n const tf = new Map<string, number>();\n for (const token of tokens) {\n tf.set(token, (tf.get(token) || 0) + 1);\n }\n return tf;\n}\n\n/**\n * Split JD into sections and identify which sections contain requirements/qualifications.\n * Words from requirement sections get a boost to prioritize technical skills over marketing fluff.\n */\nfunction splitJdSections(text: string): { requirementText: string; otherText: string } {\n const lines = text.split('\\n');\n const reqPatterns = /^(required|requirements?|minimum|preferred|qualifications?|must[\\s-]have|nice[\\s-]to[\\s-]have|what you.?ll|what we.?re looking|skills|technical|you.?ll need|responsibilities)/i;\n\n let inReqSection = false;\n const reqLines: string[] = [];\n const otherLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n // Detect section headers\n if (reqPatterns.test(trimmed.replace(/[:#*-]/g, '').trim())) {\n inReqSection = true;\n } else if (/^(about|summary|who we are|our (company|team|mission)|description|overview|benefits|perks|compensation|salary)/i.test(trimmed.replace(/[:#*-]/g, '').trim())) {\n inReqSection = false;\n }\n\n if (inReqSection) {\n reqLines.push(line);\n } else {\n otherLines.push(line);\n }\n }\n\n return {\n requirementText: reqLines.join('\\n'),\n otherText: otherLines.join('\\n'),\n };\n}\n\n/**\n * Detect multi-word technical terms (e.g. \"machine learning\", \"computer vision\", \"data pipelines\").\n * These are more valuable than individual words and should be matched as units.\n */\nfunction extractCompoundTerms(text: string): string[] {\n const patterns = [\n /\\b(machine\\s+learning)\\b/gi,\n /\\b(deep\\s+learning)\\b/gi,\n /\\b(computer\\s+vision)\\b/gi,\n /\\b(natural\\s+language\\s+processing)\\b/gi,\n /\\b(data\\s+pipelines?)\\b/gi,\n /\\b(data\\s+models?)\\b/gi,\n /\\b(data\\s+engineering)\\b/gi,\n /\\b(data\\s+structures?)\\b/gi,\n /\\b(data\\s+quality)\\b/gi,\n /\\b(data\\s+flows?)\\b/gi,\n /\\b(data\\s+orchestration)\\b/gi,\n /\\b(data\\s+warehou\\w+)\\b/gi,\n /\\b(synthetic\\s+data)\\b/gi,\n /\\b(ci\\s*\\/?\\s*cd)\\b/gi,\n /\\b(rest\\s+api)\\b/gi,\n /\\b(open\\s+source)\\b/gi,\n /\\b(human[\\s-]+in[\\s-]+the[\\s-]+loop)\\b/gi,\n /\\b(self[\\s-]+service)\\b/gi,\n /\\b(agentic\\s+workflows?)\\b/gi,\n /\\b(distributed\\s+systems?)\\b/gi,\n /\\b(cloud\\s+infrastructure)\\b/gi,\n /\\b(micro\\s*services?)\\b/gi,\n /\\b(full[\\s-]+stack)\\b/gi,\n /\\b(front[\\s-]*end)\\b/gi,\n /\\b(back[\\s-]*end)\\b/gi,\n /\\b(sql\\s*\\/?\\s*nosql)\\b/gi,\n ];\n\n const found: string[] = [];\n for (const pattern of patterns) {\n const matches = text.matchAll(pattern);\n for (const m of matches) {\n const term = m[1]?.toLowerCase().replace(/\\s+/g, ' ').trim();\n if (term && !found.includes(term)) {\n found.push(term);\n }\n }\n }\n return found;\n}\n\n/**\n * Detect likely company names, product names, and brand mentions.\n * These are proper nouns in the JD intro — not skills to match against.\n */\nfunction extractBrandNames(text: string): Set<string> {\n const brands = new Set<string>();\n\n // Common patterns: \"at <Company>\", \"<Company> is\", \"about <Company>\"\n // Also match well-known tech company names and product names\n const brandPatterns = [\n /\\bat\\s+([A-Z][a-zA-Z]+(?:\\s+[A-Z][a-zA-Z]+)*)/g,\n /(?:^|\\.\\s+)([A-Z][a-zA-Z]+(?:\\s+[A-Z][a-zA-Z]+)*)\\s+(?:is|are|was|has|Inc|Corp|Ltd|GmbH)/g,\n /\\b(?:join(?:ing)?|about)\\s+([A-Z][a-zA-Z]+)/g,\n ];\n\n for (const pattern of brandPatterns) {\n const matches = text.matchAll(pattern);\n for (const m of matches) {\n const name = m[1]?.toLowerCase();\n if (name) {\n // Add individual words from brand names\n for (const word of name.split(/\\s+/)) {\n if (word.length > 2) brands.add(word);\n }\n }\n }\n }\n\n // Well-known tech companies & products that are always noise in JDs\n const knownBrands = [\n 'apple', 'google', 'meta', 'facebook', 'amazon', 'microsoft', 'netflix',\n 'uber', 'airbnb', 'twitter', 'linkedin', 'spotify', 'stripe', 'shopify',\n 'iphone', 'ipad', 'mac', 'macbook', 'airpods', 'android', 'windows',\n 'alexa', 'siri', 'cortana', 'gmail', 'chrome', 'safari', 'firefox',\n ];\n for (const b of knownBrands) brands.add(b);\n\n // Common geographic terms that appear in JD location sections\n const locations = [\n 'zurich', 'zürich', 'berlin', 'london', 'paris', 'amsterdam', 'munich',\n 'münchen', 'new york', 'san francisco', 'seattle', 'austin', 'boston',\n 'chicago', 'toronto', 'vancouver', 'singapore', 'tokyo', 'sydney',\n 'dublin', 'bangalore', 'hyderabad', 'remote', 'hybrid', 'onsite',\n 'switzerland', 'germany', 'france', 'spain', 'italy', 'netherlands',\n 'united states', 'united kingdom', 'canada', 'australia', 'india',\n 'japan', 'china', 'brazil', 'israel', 'sweden', 'norway', 'denmark',\n 'finland', 'austria', 'belgium', 'portugal', 'ireland', 'poland',\n ];\n for (const loc of locations) {\n brands.add(loc);\n for (const part of loc.split(/\\s+/)) {\n if (part.length > 2) brands.add(part);\n }\n }\n\n return brands;\n}\n\n/**\n * Extract the most important keywords from a job description.\n *\n * Strategy:\n * 1. Extract multi-word technical terms first (highest value)\n * 2. Parse sections — boost words from requirements/qualifications sections\n * 3. Filter out company names, product names, and generic filler words\n * 4. Rank by weighted frequency, prefer technical terms\n */\nfunction extractKeywords(text: string, language: string, maxKeywords: number = 30, extraStopWords?: Set<string>): string[] {\n const langData = getLanguageData(language);\n // Merge stop words + action verbs (action verbs are resume language, not skill keywords)\n const stopWords = new Set([\n ...langData.stopWords,\n ...langData.actionVerbs,\n ...langData.actionVerbs.map((v) => simpleStem(v, language)),\n ...(extraStopWords || []),\n ]);\n\n // Step 0: Pre-process text to strip URLs, emails, and other noise\n const cleanText = stripNoise(text);\n\n // Step 1: Extract compound terms (these bypass TF ranking)\n const compoundTerms = extractCompoundTerms(cleanText);\n\n // Step 2: Detect brand/company/product names to exclude\n const brandNames = extractBrandNames(text); // use original text for brand detection (needs uppercase)\n\n // Step 3: Section-aware tokenization\n // Only use tokens from requirement sections; if no requirements detected, use everything\n const { requirementText } = splitJdSections(cleanText);\n const hasRequirementSections = requirementText.trim().length > 0;\n\n let allTokens: string[];\n if (hasRequirementSections) {\n // Requirement section tokens only — company description/about sections are noise\n allTokens = tokenize(requirementText, stopWords).filter((t) => !brandNames.has(t));\n } else {\n // No detected sections — use all text (small JDs often lack headers)\n allTokens = tokenize(cleanText, stopWords).filter((t) => !brandNames.has(t));\n }\n const stemmed = allTokens.map((t) => simpleStem(t, language));\n const tf = buildTfMap(stemmed);\n\n // Keep a mapping from stem → original token (first occurrence)\n const stemToOriginal = new Map<string, string>();\n for (let i = 0; i < allTokens.length; i++) {\n const stem = stemmed[i] ?? '';\n if (!stemToOriginal.has(stem)) {\n stemToOriginal.set(stem, allTokens[i] ?? '');\n }\n }\n\n // Step 3: Filter out words that are already part of compound terms\n const compoundsFlat = compoundTerms.join(' ').split(/\\s+/);\n const compoundWordSet = new Set(compoundsFlat);\n\n // Sort by frequency, filter noise, take top N\n const singleKeywords = [...tf.entries()]\n .filter(([stem]) => stem.length > 2)\n .filter(([stem]) => {\n const original = stemToOriginal.get(stem) || stem;\n // Skip if this word is only meaningful as part of a compound term\n if (compoundWordSet.has(original) && !allTokens.includes(original)) {\n return false;\n }\n return true;\n })\n .sort((a, b) => b[1] - a[1])\n .slice(0, maxKeywords - compoundTerms.length)\n .map(([stem]) => stemToOriginal.get(stem) || stem);\n\n // Compound terms go first, then single keywords (deduplicated)\n const seen = new Set<string>();\n const keywords: string[] = [];\n for (const term of [...compoundTerms, ...singleKeywords]) {\n if (!seen.has(term)) {\n seen.add(term);\n keywords.push(term);\n }\n }\n\n return keywords.slice(0, maxKeywords);\n}\n\n/**\n * Match job description keywords against resume content.\n * Uses stemmed matching for fuzzy equivalence.\n * Compound terms are matched by checking if all component words exist in the resume.\n */\nexport function matchJobDescription(\n resume: ResumeSchema,\n jobDescription: string,\n language: string = 'en'\n): AtsKeywordMatch {\n const langData = getLanguageData(language);\n const stopWords = new Set(langData.stopWords);\n\n // Build extra stop words from the resume owner's name and location\n const nameStopWords = new Set<string>();\n if (resume.basics?.name) {\n for (const part of resume.basics.name.toLowerCase().split(/\\s+/)) {\n if (part.length > 2) nameStopWords.add(part);\n }\n }\n if (resume.basics?.location?.city) {\n nameStopWords.add(resume.basics.location.city.toLowerCase());\n }\n if (resume.basics?.location?.region) {\n nameStopWords.add(resume.basics.location.region.toLowerCase());\n }\n\n // Extract keywords from JD, filtering out resume owner's name parts\n const jdKeywords = extractKeywords(jobDescription, language, 30, nameStopWords);\n\n // Build stemmed set from resume content\n const resumeText = extractResumeText(resume);\n const resumeTokens = tokenize(resumeText, stopWords);\n const resumeStems = new Set(resumeTokens.map((t) => simpleStem(t, language)));\n\n // Also include raw tokens for exact matching (handles acronyms, tool names)\n const resumeTokenSet = new Set(resumeTokens);\n\n // Match\n const matched: string[] = [];\n const missing: string[] = [];\n\n for (const keyword of jdKeywords) {\n // For compound terms, check if all component words match\n if (keyword.includes(' ')) {\n const parts = keyword.split(/\\s+/);\n const allPartsMatch = parts.every((part) => {\n const stem = simpleStem(part, language);\n return resumeStems.has(stem) || resumeTokenSet.has(part.toLowerCase());\n });\n if (allPartsMatch) {\n matched.push(keyword);\n } else {\n missing.push(keyword);\n }\n } else {\n const stem = simpleStem(keyword, language);\n if (resumeStems.has(stem) || resumeTokenSet.has(keyword.toLowerCase())) {\n matched.push(keyword);\n } else {\n missing.push(keyword);\n }\n }\n }\n\n const matchPercentage = jdKeywords.length > 0\n ? Math.round((matched.length / jdKeywords.length) * 100)\n : 0;\n\n // Find resume skills NOT required by the JD\n // Extract explicit skill keywords from the resume's skills section\n const resumeSkillKeywords: string[] = [];\n for (const s of resume.skills || []) {\n for (const kw of s.keywords || []) {\n resumeSkillKeywords.push(kw.toLowerCase());\n }\n }\n\n // Build stemmed set of all JD keywords for matching\n const jdStemSet = new Set<string>();\n const jdTokenSet = new Set<string>();\n for (const kw of jdKeywords) {\n jdTokenSet.add(kw.toLowerCase());\n for (const part of kw.split(/\\s+/)) {\n jdStemSet.add(simpleStem(part, language));\n jdTokenSet.add(part.toLowerCase());\n }\n }\n\n // Also stem the full JD text to catch broader matches\n const jdFullTokens = tokenize(stripNoise(jobDescription), new Set(langData.stopWords));\n const jdFullStems = new Set(jdFullTokens.map((t) => simpleStem(t, language)));\n\n const extra: string[] = [];\n const seenExtra = new Set<string>();\n for (const skill of resumeSkillKeywords) {\n const stem = simpleStem(skill, language);\n // This skill is \"extra\" if it doesn't appear anywhere in the JD\n if (!jdFullStems.has(stem) && !jdTokenSet.has(skill) && !seenExtra.has(skill)) {\n seenExtra.add(skill);\n extra.push(skill);\n }\n }\n\n return { matched, missing, extra, matchPercentage };\n}\n","import type { AtsCheck, AtsRating, AtsFitAssessment, AtsKeywordMatch } from './types';\n\nconst weightMultiplier: Record<string, number> = {\n high: 3,\n medium: 2,\n low: 1,\n};\n\n/**\n * Calculate a weighted ATS score from a set of checks.\n */\nexport function calculateScore(checks: AtsCheck[]): number {\n if (checks.length === 0) return 0;\n\n let weightedSum = 0;\n let totalWeight = 0;\n\n for (const check of checks) {\n const mult = weightMultiplier[check.weight] || 1;\n weightedSum += check.score * mult;\n totalWeight += 100 * mult;\n }\n\n return totalWeight > 0 ? Math.round((weightedSum / totalWeight) * 100) : 0;\n}\n\n/**\n * Calculate a combined score from generic checks and optional JD matching.\n */\nexport function calculateCombinedScore(genericScore: number, jdMatchPercentage?: number): number {\n if (jdMatchPercentage === undefined) return genericScore;\n return Math.round(genericScore * 0.6 + jdMatchPercentage * 0.4);\n}\n\n/**\n * Map a numeric score to a human-readable rating.\n */\nexport function scoreToRating(score: number): AtsRating {\n if (score >= 90) return 'excellent';\n if (score >= 75) return 'good';\n if (score >= 60) return 'needs-work';\n return 'poor';\n}\n\n/**\n * Generate a summary string for a given score and rating.\n */\nexport function generateSummary(score: number, rating: AtsRating, hasJd: boolean): string {\n const ratingLabel = {\n excellent: 'Excellent',\n good: 'Good',\n 'needs-work': 'Needs Work',\n poor: 'Poor',\n }[rating];\n\n const base = `ATS Score: ${score}/100 (${ratingLabel})`;\n if (hasJd) {\n return `${base} — includes job description keyword matching.`;\n }\n return `${base} — based on resume structure and content best practices.`;\n}\n\n/**\n * Assess how well a resume fits a job description based on keyword matching.\n */\nexport function assessFit(keywords: AtsKeywordMatch): AtsFitAssessment {\n const { matchPercentage, missing } = keywords;\n if (matchPercentage >= 70) {\n return {\n level: 'strong',\n message: 'Strong fit — your resume aligns well with this job description.',\n };\n }\n const topMissing = missing.slice(0, 5).join(', ');\n if (matchPercentage >= 50) {\n return {\n level: 'partial',\n message: `Partial fit — consider emphasizing transferable skills. Key gaps: ${topMissing}.`,\n };\n }\n return {\n level: 'weak',\n message: `Weak fit — this role requires skills not well represented in your resume. Major gaps: ${topMissing}.`,\n };\n}\n","import type { ResumeSchema } from '../types/resume';\nimport type { AtsResult, AtsOptions } from './types';\nimport { runGenericChecks } from './genericChecks';\nimport { matchJobDescription } from './jdMatcher';\nimport { calculateScore, calculateCombinedScore, scoreToRating, generateSummary, assessFit } from './scoring';\n\n/**\n * Run ATS analysis on a resume.\n *\n * Performs deterministic, offline checks:\n * 1. Generic best-practice checks (contact, content, structure)\n * 2. Optional job-description keyword matching\n *\n * @param resume - Validated resume data\n * @param options - ATS analysis options\n * @returns Full ATS analysis result with score, checks, and suggestions\n */\nexport function analyzeAts(resume: ResumeSchema, options: AtsOptions = {}): AtsResult {\n const language = options.language || 'en';\n\n // Run generic checks\n const checks = runGenericChecks(resume, language);\n const genericScore = calculateScore(checks);\n\n // Run JD matching if provided\n let keywords;\n let fitAssessment;\n if (options.jobDescription) {\n keywords = matchJobDescription(resume, options.jobDescription, language);\n fitAssessment = assessFit(keywords);\n }\n\n // Calculate combined score\n const finalScore = calculateCombinedScore(genericScore, keywords?.matchPercentage);\n const rating = scoreToRating(finalScore);\n const summary = generateSummary(finalScore, rating, !!keywords);\n\n return {\n score: finalScore,\n rating,\n checks,\n keywords,\n fitAssessment,\n summary,\n };\n}\n\nexport type { AtsResult, AtsOptions, AtsCheck, AtsKeywordMatch, AtsFitAssessment } from './types';\n","export function generateResumeYaml(name: string, email: string, label: string): string {\n return `# =============================================================================\n# Resume - Generated by resuml\n# Documentation: https://github.com/phoinixi/resuml\n# Schema: https://jsonresume.org/schema/\n# =============================================================================\n\n# --- Basic Information ---\nbasics:\n name: '${name}'\n label: '${label}'\n # image: 'https://example.com/photo.jpg'\n email: '${email}'\n # phone: '+1-555-123-4567'\n # url: 'https://yourwebsite.com'\n summary: >-\n Write a short professional summary here.\n This supports multi-line strings in YAML.\n location:\n # address: '123 Main Street'\n # postalCode: '12345'\n city: 'Your City'\n countryCode: 'US'\n # region: 'Your State'\n profiles:\n - network: 'LinkedIn'\n username: 'your-username'\n url: 'https://linkedin.com/in/your-username'\n - network: 'GitHub'\n username: 'your-username'\n url: 'https://github.com/your-username'\n\n# --- Work Experience ---\nwork:\n - name: 'Company Name'\n position: 'Job Title'\n url: 'https://company.com'\n startDate: '2020-01-01'\n # endDate: '2023-12-31' # Omit for current position\n summary: 'Brief description of your role and responsibilities.'\n highlights:\n - 'Key achievement or responsibility'\n - 'Another notable accomplishment'\n\n# --- Education ---\neducation:\n - institution: 'University Name'\n url: 'https://university.edu'\n area: 'Field of Study'\n studyType: 'Bachelor of Science'\n startDate: '2014-09-01'\n endDate: '2018-06-01'\n # score: '3.8'\n courses:\n - 'Relevant Course 1'\n - 'Relevant Course 2'\n\n# --- Skills ---\nskills:\n - name: 'Programming Languages'\n level: 'Expert'\n keywords:\n - 'JavaScript'\n - 'TypeScript'\n - 'Python'\n - name: 'Frameworks'\n level: 'Advanced'\n keywords:\n - 'React'\n - 'Node.js'\n\n# --- Projects ---\n# projects:\n# - name: 'Project Name'\n# description: 'Brief project description'\n# highlights:\n# - 'Key feature or result'\n# keywords:\n# - 'Technology Used'\n# startDate: '2023-01-01'\n# endDate: '2023-06-30'\n# url: 'https://github.com/you/project'\n# roles:\n# - 'Developer'\n# type: 'application'\n\n# --- Languages ---\n# languages:\n# - language: 'English'\n# fluency: 'Native speaker'\n# - language: 'Spanish'\n# fluency: 'Professional working proficiency'\n\n# --- Interests ---\n# interests:\n# - name: 'Open Source'\n# keywords:\n# - 'Contributing'\n# - 'Community'\n\n# --- References ---\n# references:\n# - name: 'Jane Smith'\n# reference: 'It was a pleasure working with...'\n\n# --- Awards ---\n# awards:\n# - title: 'Award Name'\n# date: '2023-01-01'\n# awarder: 'Organization'\n# summary: 'Description of the award'\n\n# --- Certificates ---\n# certificates:\n# - name: 'Certificate Name'\n# date: '2023-01-01'\n# issuer: 'Issuing Organization'\n# url: 'https://example.com/cert'\n\n# --- Publications ---\n# publications:\n# - name: 'Publication Title'\n# publisher: 'Publisher'\n# releaseDate: '2023-01-01'\n# url: 'https://example.com/publication'\n# summary: 'Brief description'\n\n# --- Volunteer ---\n# volunteers:\n# - organization: 'Organization Name'\n# position: 'Volunteer Role'\n# url: 'https://organization.com'\n# startDate: '2022-01-01'\n# summary: 'Description of volunteer work'\n# highlights:\n# - 'Notable contribution'\n`;\n}\n","import { createRequire } from 'module';\n\nexport interface ThemeInfo {\n name: string;\n pkg: string;\n description: string;\n}\n\nexport const KNOWN_THEMES: ThemeInfo[] = [\n { name: 'stackoverflow', pkg: 'jsonresume-theme-stackoverflow', description: 'Stack Overflow inspired theme' },\n { name: 'elegant', pkg: 'jsonresume-theme-elegant', description: 'Elegant and professional' },\n { name: 'react', pkg: 'jsonresume-theme-react', description: 'Built with React components' },\n { name: 'even', pkg: 'jsonresume-theme-even', description: 'Clean and minimal' },\n { name: 'kendall', pkg: 'jsonresume-theme-kendall', description: 'Simple and clean layout' },\n { name: 'macchiato', pkg: 'jsonresume-theme-macchiato', description: 'Beautiful and modern' },\n { name: 'flat', pkg: 'jsonresume-theme-flat', description: 'Flat design theme' },\n { name: 'class', pkg: 'jsonresume-theme-class', description: 'Classic professional look' },\n { name: 'short', pkg: 'jsonresume-theme-short', description: 'Compact single-page resume' },\n { name: 'spartan', pkg: 'jsonresume-theme-spartan', description: 'Minimalist Spartan design' },\n { name: 'paper', pkg: 'jsonresume-theme-paper', description: 'Paper-like clean design' },\n { name: 'onepage', pkg: 'jsonresume-theme-onepage', description: 'One page resume layout' },\n];\n\nexport function isThemeInstalled(pkg: string): boolean {\n try {\n const req = createRequire(process.cwd() + '/');\n req.resolve(pkg);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getInstalledVersion(pkg: string): string | null {\n try {\n const req = createRequire(process.cwd() + '/');\n const pkgJson = req(`${pkg}/package.json`) as { version?: string };\n return pkgJson.version ?? null;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,90 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+
31
+ // src/utils/themeLoader.ts
32
+ import { execFileSync } from "child_process";
33
+ import { createRequire } from "module";
34
+ var require2 = createRequire(import.meta.url);
35
+ function installTheme(packageName) {
36
+ try {
37
+ execFileSync("npm", ["install", packageName], {
38
+ stdio: ["inherit", "pipe", "pipe"],
39
+ encoding: "utf8"
40
+ });
41
+ } catch (error) {
42
+ throw new Error(`Failed to install ${packageName}: ${error.message}`);
43
+ }
44
+ }
45
+ function loadTheme(themeName, options) {
46
+ let jsonResumeThemeName;
47
+ let nativeThemeName;
48
+ const autoInstall = options?.autoInstall !== false;
49
+ try {
50
+ jsonResumeThemeName = themeName.startsWith("jsonresume-theme-") ? themeName : `jsonresume-theme-${themeName}`;
51
+ try {
52
+ return require2(jsonResumeThemeName);
53
+ } catch (_jsonResumeError) {
54
+ nativeThemeName = `@resuml/theme-${themeName}`;
55
+ try {
56
+ return require2(nativeThemeName);
57
+ } catch (_nativeError) {
58
+ if (!autoInstall) {
59
+ throw new Error(
60
+ `Theme package ${jsonResumeThemeName} or ${nativeThemeName} not found in node_modules.
61
+ Please install the theme package manually.`
62
+ );
63
+ }
64
+ console.log(`\u{1F4E6} Theme ${jsonResumeThemeName} not found. Installing...`);
65
+ try {
66
+ installTheme(jsonResumeThemeName);
67
+ console.log(`\u2705 Successfully installed ${jsonResumeThemeName}`);
68
+ return require2(jsonResumeThemeName);
69
+ } catch (installError) {
70
+ throw new Error(
71
+ `Failed to auto-install theme ${jsonResumeThemeName}: ${installError.message}`
72
+ );
73
+ }
74
+ }
75
+ }
76
+ } catch (error) {
77
+ if (error instanceof Error && error.message.includes("Failed to auto-install")) {
78
+ throw error;
79
+ }
80
+ throw new Error(`Theme package ${themeName} not found`);
81
+ }
82
+ }
83
+
84
+ export {
85
+ __commonJS,
86
+ __export,
87
+ __toESM,
88
+ loadTheme
89
+ };
90
+ //# sourceMappingURL=chunk-ZLA7NFYP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/themeLoader.ts"],"sourcesContent":["import { execFileSync } from 'child_process';\nimport { createRequire } from 'module';\n\nconst require = createRequire(import.meta.url);\n\nexport interface ThemeModule {\n render: (resume: Record<string, unknown>, options?: Record<string, unknown>) => string | Promise<string>;\n}\n\n/**\n * Install a theme package using npm\n * @param packageName The npm package name to install\n */\nfunction installTheme(packageName: string): void {\n try {\n execFileSync('npm', ['install', packageName], {\n stdio: ['inherit', 'pipe', 'pipe'],\n encoding: 'utf8',\n });\n } catch (error) {\n throw new Error(`Failed to install ${packageName}: ${(error as Error).message}`);\n }\n}\n\n/**\n * Load a theme module by name\n * @param themeName The name of the theme to load\n * @param options Optional settings (autoInstall: boolean)\n * @returns The loaded theme module\n */\nexport function loadTheme(themeName: string, options?: { autoInstall?: boolean }): ThemeModule {\n let jsonResumeThemeName: string;\n let nativeThemeName: string;\n const autoInstall = options?.autoInstall !== false;\n\n try {\n // Try loading as a JSON Resume theme\n jsonResumeThemeName = themeName.startsWith('jsonresume-theme-')\n ? themeName\n : `jsonresume-theme-${themeName}`;\n\n try {\n // Use require for CommonJS modules\n return require(jsonResumeThemeName) as ThemeModule;\n } catch (_jsonResumeError) {\n // If not found as JSON Resume theme, try as native theme\n nativeThemeName = `@resuml/theme-${themeName}`;\n try {\n return require(nativeThemeName) as ThemeModule;\n } catch (_nativeError) {\n if (!autoInstall) {\n throw new Error(\n `Theme package ${jsonResumeThemeName} or ${nativeThemeName} not found in node_modules.\\n` +\n `Please install the theme package manually.`\n );\n }\n // Both attempts failed - auto-install the theme\n console.log(`📦 Theme ${jsonResumeThemeName} not found. Installing...`);\n try {\n installTheme(jsonResumeThemeName);\n console.log(`✅ Successfully installed ${jsonResumeThemeName}`);\n // Try requiring again after installation\n return require(jsonResumeThemeName) as ThemeModule;\n } catch (installError) {\n throw new Error(\n `Failed to auto-install theme ${jsonResumeThemeName}: ${\n (installError as Error).message\n }`\n );\n }\n }\n }\n } catch (error) {\n // Re-throw if it's already our custom error\n if (error instanceof Error && error.message.includes('Failed to auto-install')) {\n throw error;\n }\n throw new Error(`Theme package ${themeName} not found`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAE9B,IAAMA,WAAU,cAAc,YAAY,GAAG;AAU7C,SAAS,aAAa,aAA2B;AAC/C,MAAI;AACF,iBAAa,OAAO,CAAC,WAAW,WAAW,GAAG;AAAA,MAC5C,OAAO,CAAC,WAAW,QAAQ,MAAM;AAAA,MACjC,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,qBAAqB,WAAW,KAAM,MAAgB,OAAO,EAAE;AAAA,EACjF;AACF;AAQO,SAAS,UAAU,WAAmB,SAAkD;AAC7F,MAAI;AACJ,MAAI;AACJ,QAAM,cAAc,SAAS,gBAAgB;AAE7C,MAAI;AAEF,0BAAsB,UAAU,WAAW,mBAAmB,IAC1D,YACA,oBAAoB,SAAS;AAEjC,QAAI;AAEF,aAAOA,SAAQ,mBAAmB;AAAA,IACpC,SAAS,kBAAkB;AAEzB,wBAAkB,iBAAiB,SAAS;AAC5C,UAAI;AACF,eAAOA,SAAQ,eAAe;AAAA,MAChC,SAAS,cAAc;AACrB,YAAI,CAAC,aAAa;AAChB,gBAAM,IAAI;AAAA,YACR,iBAAiB,mBAAmB,OAAO,eAAe;AAAA;AAAA,UAE5D;AAAA,QACF;AAEA,gBAAQ,IAAI,mBAAY,mBAAmB,2BAA2B;AACtE,YAAI;AACF,uBAAa,mBAAmB;AAChC,kBAAQ,IAAI,iCAA4B,mBAAmB,EAAE;AAE7D,iBAAOA,SAAQ,mBAAmB;AAAA,QACpC,SAAS,cAAc;AACrB,gBAAM,IAAI;AAAA,YACR,gCAAgC,mBAAmB,KAChD,aAAuB,OAC1B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,wBAAwB,GAAG;AAC9E,YAAM;AAAA,IACR;AACA,UAAM,IAAI,MAAM,iBAAiB,SAAS,YAAY;AAAA,EACxD;AACF;","names":["require"]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import { R as ResumeSchema } from './themeLoader-C7CBqNiC.cjs';
4
- export { l as loadResumeFiles, a as loadTheme, p as processResumeData } from './themeLoader-C7CBqNiC.cjs';
3
+ import { R as ResumeSchema } from './themeLoader-C7CBqNiC.js';
4
+ export { l as loadResumeFiles, a as loadTheme, p as processResumeData } from './themeLoader-C7CBqNiC.js';
5
5
 
6
6
  interface ThemeConfig {
7
7
  sections?: {