Resume/Cover Letter Snippet Generator

Resume/Cover Letter Snippet Generator

Resume/Cover Letter Snippet Generator

Enter your raw professional achievements. Format each achievement as a single line, ending with quantification (a number, percentage, or dollar amount).

These will be used for filtering.

Select filters to dynamically generate a targeted set of bullet points for your application.

Filter & Theme

Skill Tags (Click to select)

No skills entered in Data Entry tab.

Generated Snippets

No skills entered in Data Entry tab.

'; return; } tagsContainer.innerHTML = availableSkills.map(skill => { const skillId = skill.replace(/\s/g, '_').toLowerCase(); const isSelected = selectedSkills.has(skillId); return `${escapeHtml(skill)}`; }).join(''); } /** Toggles a skill filter */ window.rclgToggleSkill = (skillId) => { if (selectedSkills.has(skillId)) { selectedSkills.delete(skillId); } else { selectedSkills.add(skillId); } renderSkillTags(); rclgGenerateSnippets(); // Regenerate output immediately }; // === GENERATOR LOGIC === /** Generates the final, filtered, and formatted snippets */ window.rclgGenerateSnippets = () => { if (!outputArea || !themeSelect || !actionSelect) return; const themeFilter = themeSelect.value; const verbStyle = actionSelect.value; if (rawData.length === 0) { outputArea.value = "Please return to the Data Entry tab and input your quantified achievements."; return; } let filteredSnippets = rawData.filter(item => { // 1. Theme Filtering let themeMatch = themeFilter === 'all'; if (!themeMatch) { const keywords = thematicKeywords[themeFilter]; if (keywords) { themeMatch = keywords.some(keyword => item.words.includes(keyword)); } } // 2. Skill Filtering let skillMatch = true; if (selectedSkills.size > 0) { // Check if the achievement contains ANY of the selected skill keywords skillMatch = availableSkills.some(skill => { const skillId = skill.replace(/\s/g, '_').toLowerCase(); if (selectedSkills.has(skillId)) { // Simple check: does the achievement text contain the skill name? return item.text.toLowerCase().includes(skill.toLowerCase()); } return false; }); // If no skills are selected, we don't filter by skill, so we use the default rawData filter if (selectedSkills.size > 0 && skillMatch) { // Passed skill filter } else if (selectedSkills.size > 0 && !skillMatch) { // Failed skill filter return false; } } return themeMatch; // Already combined skill match logic above }); // 3. Formatting let output = ''; filteredSnippets.forEach(item => { let formattedLine = item.text; // --- Verb Rewriting --- // Find the first word and attempt translation based on map const firstWord = formattedLine.split(/\s+/)[0]; let replacementVerb = firstWord; if (verbStyle === 'present') { replacementVerb = verbMap[firstWord] || firstWord; } else if (verbStyle === 'past') { // Simple inverse mapping for common verbs const presentForm = verbMap[firstWord]; replacementVerb = presentForm ? firstWord : firstWord; // If it's not a common mapped past tense, leave it } // Reconstruct line with new verb formattedLine = replacementVerb.charAt(0).toUpperCase() + replacementVerb.slice(1) + formattedLine.slice(firstWord.length); output += '• ' + formattedLine + '\n'; }); if (filteredSnippets.length === 0) { output = "No snippets matched your current theme and skill filters."; } outputArea.value = output.trim(); }; // === TAB AND NAV LOGIC === /** Switches tabs */ window.rclgShowTab = (tabId, element) => { if (!container || !tabLinks) return; container.querySelectorAll('.rclg-tab-content').forEach(tab => tab.classList.remove('rclg-active')); container.querySelectorAll('.rclg-tab-link').forEach(link => link.classList.remove('rclg-active')); const tabToShow = container.querySelector('#' + tabId); if (tabToShow) tabToShow.classList.add('rclg-active'); if (element) element.classList.add('rclg-active'); currentTabId = tabId; updateNavButtons(); // Sync data and render tags when switching to generator tab if (tabId === 'rclg-tab-generator') { if (processInputData()) { renderSkillTags(); rclgGenerateSnippets(); } else { outputArea.value = "Please return to the Data Entry tab and input your quantified achievements."; renderSkillTags(); } } }; /** Handles nav buttons */ window.rclgNavigateTabs = (isNext) => { if (!container || !tabLinks) return; // Ensure data is processed before leaving tab 1 if (currentTabId === 'rclg-tab-data-entry' && isNext) { if (!processInputData()) { showMessage("Please input achievements before proceeding.", true); return; } } const targetTabId = isNext ? 'rclg-tab-generator' : 'rclg-tab-data-entry'; const targetTabLink = container.querySelector(`.rclg-tab-link[onclick*="'${targetTabId}'"]`); if(targetTabLink) targetTabLink.click(); }; /** Updates nav button states */ function updateNavButtons() { if (!prevBtn || !nextBtn) return; prevBtn.disabled = currentTabId === 'rclg-tab-data-entry'; nextBtn.disabled = currentTabId === 'rclg-tab-generator'; } // --- PDF & Copy EXPORT --- window.rclgCopyOutput = () => { if (!outputArea) return; outputArea.select(); try { document.execCommand('copy'); showMessage('Snippets copied to clipboard!', false); } catch (err) { showMessage('Failed to copy. Please copy manually.', true); } }; window.rclgDownloadPDF = () => { if (typeof jsPDF === 'undefined') { showMessage("PDF library not loaded.", true); return; } const content = outputArea.value.trim(); if (!content || content.includes('No snippets matched')) { showMessage("Please generate valid snippets before downloading.", true); return; } try { const doc = new jsPDF(); const pageMargin = 40; const contentWidth = doc.internal.pageSize.getWidth() - (pageMargin * 2); let y = pageMargin; const PRIMARY_COLOR_HEX = '#374151'; const ACCENT_COLOR_HEX = '#f97316'; // 1. Title doc.setFontSize(18); doc.setFont(undefined, 'bold'); doc.setTextColor(PRIMARY_COLOR_HEX); doc.text("Targeted Resume Snippets", pageMargin, y); y += 25; // 2. Metadata doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.text(`Theme: ${themeSelect.options[themeSelect.selectedIndex].text}`, pageMargin, y); doc.text(`Action Style: ${actionSelect.options[actionSelect.selectedIndex].text}`, pageMargin + 150, y); y += 15; doc.text(`Selected Skills: ${Array.from(selectedSkills).map(s => s.replace(/_/g, ' ').toUpperCase()).join(', ')}`, pageMargin, y); y += 25; // 3. Snippets (using Courier for clean bullet points) doc.setFont('courier', 'normal'); doc.setFontSize(10); doc.setTextColor(PRIMARY_COLOR_HEX); // Use primary color for impact const lines = doc.splitTextToSize(content, contentWidth); lines.forEach(line => { if (y > doc.internal.pageSize.getHeight() - pageMargin) { doc.addPage(); y = pageMargin; } doc.text(line, pageMargin, y); y += 12; // Standard line height for courier }); doc.save("Targeted_Snippets.pdf"); } catch (e) { console.error("Error generating PDF:", e); showMessage("An error occurred while generating the PDF.", true); } }; // --- Initial Load --- renderSkillTags(); updateNavButtons(); });
Scroll to Top