From 6fa8c58179917b39a75c57d7320db419d69ee821 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Jul 2026 09:19:06 +0000 Subject: [PATCH] feat: add Carbone tags help - view in-app modal and download as .docx --- renderer/carbone-service.js | 122 ++++++ .../HELP_TAGS_REFERENCE.docx | Bin 0 -> 38295 bytes .../carbone-templates/HELP_TAGS_REFERENCE.md | 364 ++++++++++++++++++ static/carbone.js | 34 ++ static/index.html | 2 + 5 files changed, 522 insertions(+) create mode 100644 renderer/carbone-templates/HELP_TAGS_REFERENCE.docx create mode 100644 renderer/carbone-templates/HELP_TAGS_REFERENCE.md diff --git a/renderer/carbone-service.js b/renderer/carbone-service.js index 7fabf9b..847e1dc 100644 --- a/renderer/carbone-service.js +++ b/renderer/carbone-service.js @@ -473,6 +473,128 @@ router.get('/master-template', async (req, res) => { } }); +// GET /api/carbone/help-docx - Download tags reference as .docx +router.get('/help-docx', (req, res) => { + const helpPath = path.join(TEMPLATES_DIR, 'HELP_TAGS_REFERENCE.docx'); + if (fs.existsSync(helpPath)) { + res.download(helpPath, 'Carbone_Tags_Reference.docx'); + } else { + res.status(404).json({ error: 'Help file not found' }); + } +}); + +// GET /api/carbone/help - Get tags reference as JSON (for in-app viewing) +router.get('/help', (req, res) => { + res.json({ + sections: [ + { + title: '1. Personal Details', + type: 'simple', + tags: [ + { tag: '{d.fullName}', desc: 'Full name (first + last)' }, + { tag: '{d.firstName}', desc: 'First name only' }, + { tag: '{d.lastName}', desc: 'Last name only' }, + { tag: '{d.email}', desc: 'Email address' }, + { tag: '{d.phone}', desc: 'Phone number' }, + { tag: '{d.address}', desc: 'Physical address' }, + { tag: '{d.linkedin}', desc: 'LinkedIn profile URL' }, + { tag: '{d.github}', desc: 'GitHub profile URL' }, + { tag: '{d.website}', desc: 'Personal website' }, + { tag: '{d.summary}', desc: 'Professional summary paragraph' }, + { tag: '{d.generationDate}', desc: 'Date the CV was generated' } + ] + }, + { + title: '2. Work Experience (Loop)', + type: 'loop', + note: 'Carbone auto-detects loops from [i]. Section repeats for each job.', + tags: [ + { tag: '{d.experience[i].position}', desc: 'Job title' }, + { tag: '{d.experience[i].company}', desc: 'Company name' }, + { tag: '{d.experience[i].location}', desc: 'Work location' }, + { tag: '{d.experience[i].startDate}', desc: 'Start date (Mon YYYY)' }, + { tag: '{d.experience[i].endDate}', desc: 'End date or "Present"' }, + { tag: '{d.experience[i].duration}', desc: 'Calculated duration (e.g., 4.5 years)' }, + { tag: '{d.experience[i].description}', desc: 'Job description' }, + { tag: '{d.experience[i].skillsUsed}', desc: 'Comma-separated skills used' }, + { tag: '{d.experience[i].achievements[j]}', desc: 'Achievement bullet (sub-loop)' } + ] + }, + { + title: '3. Skills', + type: 'loop', + tags: [ + { tag: '{d.skills[i].name}', desc: 'Skill name' }, + { tag: '{d.skills[i].category}', desc: 'Skill category' }, + { tag: '{d.skills[i].proficiency}', desc: 'Proficiency level' }, + { tag: '{d.skills[i].years}', desc: 'Years of experience (dynamic)' }, + { tag: '{d.skillsByCategory[i].category}', desc: 'Category name (grouped)' }, + { tag: '{d.skillsByCategory[i].skills[j].name}', desc: 'Skill in category (grouped)' }, + { tag: '{d.skillsByCategory[i].skills[j].years}', desc: 'Years in category (grouped)' } + ] + }, + { + title: '4. Education (Loop)', + type: 'loop', + tags: [ + { tag: '{d.education[i].degree}', desc: 'Degree name' }, + { tag: '{d.education[i].field}', desc: 'Field of study' }, + { tag: '{d.education[i].institution}', desc: 'University/institution' }, + { tag: '{d.education[i].startDate}', desc: 'Start date' }, + { tag: '{d.education[i].endDate}', desc: 'End date' }, + { tag: '{d.education[i].grade}', desc: 'Grade/result' } + ] + }, + { + title: '5. Certifications (Loop)', + type: 'loop', + tags: [ + { tag: '{d.certifications[i].name}', desc: 'Certification name' }, + { tag: '{d.certifications[i].issuer}', desc: 'Issuing organization' }, + { tag: '{d.certifications[i].date}', desc: 'Issue date' }, + { tag: '{d.certifications[i].expiryDate}', desc: 'Expiry date (if any)' } + ] + }, + { + title: '6. Conditionals (Show/Hide)', + type: 'simple', + note: 'Show content only when a field has a value (or is empty).', + tags: [ + { tag: '{d.field:showBegin}...{d.field:showEnd}', desc: 'Show if NOT empty' }, + { tag: '{d.field:hideBegin}...{d.field:hideEnd}', desc: 'Show if empty' }, + { tag: '{d.field:ifEM(replacement text)}', desc: 'Show text if field is empty' }, + { tag: '{d.field:ifNEM(replacement text)}', desc: 'Show text if field is not empty' }, + { tag: '{d.field:ifEQ(value):showBegin}...{d.field:showEnd}', desc: 'Show if equals value' }, + { tag: '{d.field:ifContain(text):showBegin}...{d.field:showEnd}', desc: 'Show if contains text' }, + { tag: '{d.field:ifGT(5):showBegin}...{d.field:showEnd}', desc: 'Show if greater than value' } + ] + }, + { + title: '7. Formatting', + type: 'simple', + tags: [ + { tag: '{d.field:formatD(YYYY-MM-DD)}', desc: 'Format date: 2022-01-01' }, + { tag: '{d.field:formatD(MMM YYYY)}', desc: 'Format date: Jan 2022' }, + { tag: '{d.field:formatN(0.0)}', desc: 'Format number with 1 decimal' }, + { tag: '{d.field:upperCase}', desc: 'Convert to UPPERCASE' }, + { tag: '{d.field:lowerCase}', desc: 'Convert to lowercase' }, + { tag: '{d.field:ucWords}', desc: 'Capitalize Each Word' }, + { tag: '{d.field:substr(0, 100)}', desc: 'First 100 characters' } + ] + }, + { + title: '8. Array Operations', + type: 'simple', + tags: [ + { tag: '{d.skills:arrayJoin(, )}', desc: 'Join all items with separator' }, + { tag: '{d.skills:arrayMap(name):arrayJoin(, )}', desc: 'Extract field and join' }, + { tag: '{d.experience:count}', desc: 'Count items in array' } + ] + } + ] + }); +}); + // POST /api/carbone/templates/upload - Upload a custom .docx template router.post('/templates/upload', upload.single('template'), (req, res) => { if (!req.file) { diff --git a/renderer/carbone-templates/HELP_TAGS_REFERENCE.docx b/renderer/carbone-templates/HELP_TAGS_REFERENCE.docx new file mode 100644 index 0000000000000000000000000000000000000000..33d755a3f51bbebab2e5c633ffcf705260bb1527 GIT binary patch literal 38295 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⪙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 2022-01-01 +{d.experience[i].startDate:formatD(MMM YYYY)} -> Jan 2022 +{d.experience[i].startDate:formatD(DD/MM/YYYY)} -> 01/01/2022 +``` + +Note: Our system already pre-formats dates as "Mon YYYY", so you typically +don't need this formatter unless you want a different format. + +### Number Formatting: `:formatN` + +``` +{d.skills[i].years:formatN(0.0)} -> 8.5 +{d.skills[i].years:formatN(0)} -> 9 +``` + +### Case Conversion + +``` +{d.fullName:upperCase} -> JOHN SMITH +{d.fullName:lowerCase} -> john smith +{d.fullName:ucFirst} -> John smith +{d.fullName:ucWords} -> John Smith +``` + +### Text Operations + +``` +{d.summary:substr(0, 100)} -> First 100 characters of summary +{d.summary:slice(0, 50)} -> First 50 characters +{d.email:padl(30)} -> Padded to 30 chars on the left +{d.email:padr(30)} -> Padded to 30 chars on the right +``` + +--- + +## 8. Comparison Conditionals + +These conditionals compare a field to a specific value: + +### If Equal: `:ifEQ` + +``` +{d.skills[i].proficiency:ifEQ(Expert):showBegin} +This person is an expert! +{d.skills[i].proficiency:showEnd} +``` + +### If Not Equal: `:ifNE` + +``` +{d.experience[i].endDate:ifNE():showBegin} +(Former position) +{d.experience[i].endDate:showEnd} +``` + +### If Greater Than: `:ifGT` + +``` +{d.skills[i].years:ifGT(5):showBegin}Senior level{d.skills[i].years:showEnd} +``` + +### If Greater Than or Equal: `:ifGTE` + +``` +{d.skills[i].years:ifGTE(3):showBegin}Experienced{d.skills[i].years:showEnd} +``` + +### If Less Than: `:ifLT` + +``` +{d.skills[i].years:ifLT(2):showBegin}Junior level{d.skills[i].years:showEnd} +``` + +### If Contains: `:ifContain` + +``` +{d.skills[i].name:ifContain(Azure):showBegin}Cloud certified{d.skills[i].name:showEnd} +``` + +--- + +## 9. Array Operations + +### Array Join: `:arrayJoin` + +Join all items in an array with a separator: + +``` +{d.skills:arrayJoin(, )} -> C#, Azure, React, Docker +``` + +### Array Map: `:arrayMap` + +Extract a specific field from all array items: + +``` +{d.skills:arrayMap(name):arrayJoin(, )} -> C#, Azure, React, Docker +``` + +### Count: `:count` + +Count items in an array: + +``` +{d.experience:count} -> 3 +{d.skills:count} -> 7 +``` + +### Length: `:len` + +String length: + +``` +{d.summary:len} -> 145 +``` + +--- + +## 10. Complete Example Template + +Here is how a complete section of your Word document might look: + +``` +{d.fullName} +{d.email} | {d.phone} | {d.address} +{d.linkedin:showBegin}LinkedIn: {d.linkedin} | {d.linkedin:showEnd} +{d.github:showBegin}GitHub: {d.github}{d.github:showEnd} + +PROFESSIONAL SUMMARY +{d.summary} + +WORK EXPERIENCE +{d.experience[i].position} at {d.experience[i].company} +{d.experience[i].startDate} - {d.experience[i].endDate} ({d.experience[i].duration}) +{d.experience[i].location:showBegin}Location: {d.experience[i].location}{d.experience[i].location:showEnd} +{d.experience[i].description} + +Achievements: +• {d.experience[i].achievements[j]} + +Skills used: {d.experience[i].skillsUsed} + +SKILLS +{d.skillsByCategory[i].category}: +• {d.skillsByCategory[i].skills[j].name} ({d.skillsByCategory[i].skills[j].years}y) +{d.skillsByCategory[i].skills[j].proficiency:showBegin} - {d.skillsByCategory[i].skills[j].proficiency}{d.skillsByCategory[i].skills[j].proficiency:showEnd} + +EDUCATION +{d.education[i].degree} in {d.education[i].field} +{d.education[i].institution} +{d.education[i].startDate} - {d.education[i].endDate} +{d.education[i].grade:showBegin}Grade: {d.education[i].grade}{d.education[i].grade:showEnd} + +CERTIFICATIONS +• {d.certifications[i].name} - {d.certifications[i].issuer} ({d.certifications[i].date}) + +Generated on {d.generationDate} +``` + +--- + +## Quick Reference Card + +| Syntax | Meaning | +|--------|---------| +| `{d.field}` | Simple text replacement | +| `{d.array[i].field}` | Loop - repeats for each array item | +| `{d.array[i].subarray[j].field}` | Nested loop | +| `:showBegin` / `:showEnd` | Show content if field is not empty | +| `:hideBegin` / `:hideEnd` | Show content if field is empty | +| `:ifEM(text)` | Show text if field is empty | +| `:ifNEM(text)` | Show text if field is not empty | +| `:ifEQ(value)` | Show if field equals value | +| `:ifNE(value)` | Show if field does not equal value | +| `:ifGT(value)` | Show if field is greater than value | +| `:ifGTE(value)` | Show if field is greater than or equal | +| `:ifLT(value)` | Show if field is less than value | +| `:ifLTE(value)` | Show if field is less than or equal | +| `:ifContain(text)` | Show if field contains text | +| `:formatD(YYYY-MM-DD)` | Format date | +| `:formatN(0.0)` | Format number | +| `:upperCase` / `:lowerCase` | Case conversion | +| `:ucFirst` / `:ucWords` | Capitalize first letter / each word | +| `:arrayJoin(, )` | Join array with separator | +| `:count` | Count array items | +| `:substr(0, 100)` | Substring | +| `:padl(30)` / `:padr(30)` | Pad string to length | \ No newline at end of file diff --git a/static/carbone.js b/static/carbone.js index ef1324e..644dfd6 100644 --- a/static/carbone.js +++ b/static/carbone.js @@ -149,4 +149,38 @@ async function deleteCarboneTemplate(templateId) { } catch (e) { toast('Delete failed: ' + e.message, 'error'); } +} + +// ============================================================ +// TAGS HELP - View in app +// ============================================================ +async function viewTagsHelp() { + try { + const resp = await fetch(CARBONE_API + '/help'); + const data = await resp.json(); + + let html = '
'; + for (const section of data.sections) { + html += `

${section.title}

`; + if (section.note) html += `

${section.note}

`; + html += ''; + for (const t of section.tags) { + html += ``; + } + html += '
TagDescription
${escapeHtml(t.tag)}${escapeHtml(t.desc)}
'; + } + html += '
'; + html += '
'; + + showModal(html, 'Carbone Tags Reference'); + } catch (e) { + toast('Failed to load help: ' + e.message, 'error'); + } +} + +// ============================================================ +// TAGS HELP - Download .docx +// ============================================================ +function downloadHelpDocx() { + window.open(CARBONE_API + '/help-docx', '_blank'); } \ No newline at end of file diff --git a/static/index.html b/static/index.html index f408f1d..386190e 100644 --- a/static/index.html +++ b/static/index.html @@ -73,6 +73,8 @@ 4. Generate CVs by merging candidate data with your template -> PDF + +
Upload Custom Template