From 3bfa1222e45a506e46eff5555859d37c1198b69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Desmaretz?= Date: Fri, 26 Jan 2024 00:06:26 +0100 Subject: [PATCH] Add Languages --- cv/cv.typ | 561 +++++++++++++++++++++++++++++------------------------- main.typ | 55 +++--- 2 files changed, 331 insertions(+), 285 deletions(-) diff --git a/cv/cv.typ b/cv/cv.typ index 51a5950..c0d7146 100644 --- a/cv/cv.typ +++ b/cv/cv.typ @@ -2,331 +2,374 @@ // set rules #let setrules(uservars, doc) = { - set text( - font: uservars.bodyfont, - size: uservars.fontsize, - hyphenate: false, - ) + set text(font: uservars.bodyfont, size: uservars.fontsize, hyphenate: false) - set list( - spacing: uservars.linespacing - ) + set list(spacing: uservars.linespacing) - set par( - leading: uservars.linespacing, - justify: true, - ) + set par(leading: uservars.linespacing, justify: true) - doc + doc } // show rules #let showrules(uservars, doc) = { - // uppercase section headings - show heading.where( - level: 2, - ): it => block(width: 100%)[ - #set align(left) - #set text(font: uservars.headingfont, size: 1em, weight: "bold") - #if (uservars.at("headingsmallcaps", default:false)) { - smallcaps(it.body) - } else { - it.body - } - #v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line - ] + // uppercase section headings + show heading.where(level: 2): it => block(width: 100%)[ + #set align(left) + #set text(font: uservars.headingfont, size: 1em, weight: "bold") + #if (uservars.at("headingsmallcaps", default: false)) { + smallcaps(it.body) + } else { + it.body + } + #v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line + ] - // name title - show heading.where( - level: 1, - ): it => block(width: 100%)[ - #set text(font: uservars.headingfont, size: 2em, weight: "bold") - #if (uservars.at("headingsmallcaps", default:false)) { - smallcaps(it.body) - } else { - // upper(it.body) - it.body - } - #v(2pt) - ] + // name title + show heading.where(level: 1): it => block(width: 100%)[ + #set text(font: uservars.headingfont, size: 2em, weight: "bold") + #if (uservars.at("headingsmallcaps", default: false)) { + smallcaps(it.body) + } else { + // upper(it.body) + it.body + } + #v(2pt) + ] - doc + doc } // set page layout #let cvinit(doc) = { - doc = setrules(doc) - doc = showrules(doc) + doc = setrules(doc) + doc = showrules(doc) - doc + doc } // address #let addresstext(lang, info, uservars) = { - if uservars.showAddress { - block(width: 100%)[ - #info.personal.location.city, #info.personal.location.region, #info.personal.location.country - #v(-4pt) - ] - } else {none} + if uservars.showAddress { + block( + width: 100%, + )[ + #info.personal.location.city, #info.personal.location.region, #info.personal.location.country + #v(-4pt) + ] + } else { none } } #let fa(body) = { - set text(font:"FontAwesome") - [#body] + set text(font: "FontAwesome") + [#body] } +#let contacttext(lang, info, uservars) = block( + width: 100%, +)[ + #let profiles = ( + box(link("mailto:" + info.personal.email)[#fa(" ") #info.personal.email]), + if uservars.showNumber { box(link("tel:" + info.personal.phone)[#fa("") #info.personal.phone]) } else { none }, + if info.personal.at("url", default: none) != none { + box( + link(info.personal.url)[#fa(" ") #info.personal.url.split("//").at(1)], + ) + }, + ).filter(it => it != none) // filter out none elements from the profile array -#let contacttext(lang, info, uservars) = block(width: 100%)[ - #let profiles = ( - box(link("mailto:" + info.personal.email)[#fa(" ") #info.personal.email]), - if uservars.showNumber {box(link("tel:" + info.personal.phone)[#fa("") #info.personal.phone])} else {none}, - if info.personal.at("url", default: none) != none { - box(link(info.personal.url)[#fa(" ") #info.personal.url.split("//").at(1)]) - } - ).filter(it => it != none) // filter out none elements from the profile array - - #if info.personal.profiles.len() > 0 { - for profile in info.personal.profiles { - profiles.push( - box(link(profile.url)[#profile.username]) - ) - } + #if info.personal.profiles.len() > 0 { + for profile in info.personal.profiles { + profiles.push(box(link(profile.url)[#profile.username])) } + } - #set text(font: uservars.bodyfont, weight: "light", size: uservars.fontsize * 1) - #pad(x: 0em)[ - #profiles.join([#sym.space.en|#sym.space.en]) - ] + #set text(font: uservars.bodyfont, weight: "light", size: uservars.fontsize * 1) + #pad(x: 0em)[ + #profiles.join([#sym.space.en|#sym.space.en]) + ] ] #let cvheading(lang, info, uservars) = { - align(center)[ - = #info.personal.name - #addresstext(lang, info, uservars) - #contacttext(lang, info, uservars) - ] + align(center)[ + = #info.personal.name + #addresstext(lang, info, uservars) + #contacttext(lang, info, uservars) + ] } #let cvwork(lang, info, isbreakable: true) = { - if info.experience != none {block[ - == #info.experience.title - #for w in info.experience.content { - block(width: 100%, breakable: isbreakable)[ - #if w.url != none [ - *#link(w.url)[#w.with]* #h(1fr) *#w.where* \ - ] else [ - *#w.with* #h(1fr) *#w.where* \ - ] + if info.experience != none { + block[ + == #info.experience.title + #for w in info.experience.content { + block(width: 100%, breakable: isbreakable)[ + #if w.url != none [ + *#link(w.url)[#w.with]* #h(1fr) *#w.where* \ + ] else [ + *#w.with* #h(1fr) *#w.where* \ + ] + ] + // create a block layout for each work entry + let index = 0 + for p in w.what { + if index != 0 { v(0.6em) } + block( + width: 100%, + breakable: isbreakable, + above: 0.6em, + )[ + // parse ISO date strings into datetime objects + #let start = utils.strpdate(lang, p.startDate) + #let end = utils.strpdate(lang, p.endDate) + // line 2: position and date range + #text(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#p.what #h(1fr) + #start #sym.dash.en #end] \ + // highlights or description + #for hi in p.why [ + - #text(weight: "light")[#eval(hi, mode: "markup")] ] - // create a block layout for each work entry - let index = 0 - for p in w.what { - if index != 0 {v(0.6em)} - block(width: 100%, breakable: isbreakable, above: 0.6em)[ - // parse ISO date strings into datetime objects - #let start = utils.strpdate(lang, p.startDate) - #let end = utils.strpdate(lang, p.endDate) - // line 2: position and date range - #text(style: "italic")[#p.what] #h(1fr) - #start #sym.dash.en #end \ - // highlights or description - #for hi in p.why [ - - #eval(hi, mode: "markup") - ] - ] - index = index + 1 - } + ] + index = index + 1 } - ]} + } + ] + } } #let cveducation(lang, info, isbreakable: true) = { - let education = info.education - if education != none {block[ - == #education.title - #for edu in education.content { - let start = utils.strpdate(lang, edu.startDate) - let end = utils.strpdate(lang, edu.endDate) - let eduurl = edu.at("url", default: none) + let education = info.education + if education != none { + block[ + == #education.title + #for edu in education.content { + let start = utils.strpdate(lang, edu.startDate) + let end = utils.strpdate(lang, edu.endDate) + let eduurl = edu.at("url", default: none) - // create a block layout for each education entry - block(width: 100%, breakable: isbreakable)[ - // line 1: institution and location - #if eduurl != none [ - *#link(eduurl)[#edu.with]* #h(1fr) *#edu.where* \ - ] else [ - *#edu.with* #h(1fr) *#edu.where* \ - ] - // line 2: degree and date - #text(style: "italic")[#edu.what] #h(1fr) - #start #sym.dash.en #end \ - - #for hi in edu.why [ - - #eval(hi, mode: "markup") - ] + // create a block layout for each education entry + block( + width: 100%, + breakable: isbreakable, + )[ + // line 1: institution and location + #if eduurl != none { + text(weight: "extrabold")[ + #link(eduurl)[#edu.with] #h(1fr) #edu.where \ ] - } - ]} + } else { + text(weight: "extrabold")[ + #edu.with #h(1fr) #edu.where \ + ] + } + // line 2: degree and date + #text(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#edu.what #h(1fr) + #start #sym.dash.en #end] \ + + #for hi in edu.why [ + - #text(weight: "light")[#eval(hi, mode: "markup")] + ] + ] + } + ] + } } #let cvaffiliations(lang, info, isbreakable: true) = { - if info.affiliations != none {block[ - == Leadership & Activities - #for org in info.affiliations { - // parse ISO date strings into datetime objects - let start = utils.strpdate(lang, org.startDate) - let end = utils.strpdate(lang, org.endDate) + if info.affiliations != none { + block[ + == Leadership & Activities + #for org in info.affiliations { + // parse ISO date strings into datetime objects + let start = utils.strpdate(lang, org.startDate) + let end = utils.strpdate(lang, org.endDate) - // create a block layout for each affiliation entry - block(width: 100%, breakable: isbreakable)[ - // line 1: organization and location - #if org.url != none [ - *#link(org.url)[#org.with]* #h(1fr) *#org.where* \ - ] else [ - *#org.with* #h(1fr) *#org.where* \ - ] - // line 2: position and date - #text(style: "italic")[#org.position] #h(1fr) - #start #sym.dash.en #end \ - // highlights or description - #if org.highlights != none { - for hi in org.highlights [ - - #eval(hi, mode: "markup") - ] - } else {} + // create a block layout for each affiliation entry + block(width: 100%, breakable: isbreakable)[ + // line 1: organization and location + #if org.url != none [ + *#link(org.url)[#org.with]* #h(1fr) *#org.where* \ + ] else [ + *#org.with* #h(1fr) *#org.where* \ + ] + // line 2: position and date + #text(style: "italic")[#org.position] #h(1fr) + #start #sym.dash.en #end \ + // highlights or description + #if org.highlights != none { + for hi in org.highlights [ + - #eval(hi, mode: "markup") ] - } - ]} + } else {} + ] + } + ] + } } #let cvprojects(lang, info, isbreakable: true) = { - if info.projects != none {block[ - == Projects - #for project in info.projects { - // parse ISO date strings into datetime objects - let start = utils.strpdate(lang, project.startDate) - let end = utils.strpdate(lang, project.endDate) - // create a block layout for each project entry - block(width: 100%, breakable: isbreakable)[ - // line 1: project name - #if project.url != none [ - *#link(project.url)[#project.name]* \ - ] else [ - *#project.name* \ - ] - // line 2: organization and date - #text(style: "italic")[#project.affiliation] #h(1fr) #start #sym.dash.en #end \ - // summary or description - #for hi in project.highlights [ - - #eval(hi, mode: "markup") - ] - ] - } - ]} + if info.projects != none { + block[ + == Projects + #for project in info.projects { + // parse ISO date strings into datetime objects + let start = utils.strpdate(lang, project.startDate) + let end = utils.strpdate(lang, project.endDate) + // create a block layout for each project entry + block( + width: 100%, + breakable: isbreakable, + )[ + // line 1: project name + #if project.url != none [ + *#link(project.url)[#project.name]* \ + ] else [ + *#project.name* \ + ] + // line 2: organization and date + #text(style: "italic")[#project.affiliation] #h(1fr) #start #sym.dash.en #end \ + // summary or description + #for hi in project.highlights [ + - #eval(hi, mode: "markup") + ] + ] + } + ] + } } #let cvawards(lang, info, isbreakable: true) = { - if info.awards != none {block[ - == Honors & Awards - #for award in info.awards { - // parse ISO date strings into datetime objects - let date = utils.strpdate(lang, award.date) - // create a block layout for each award entry - block(width: 100%, breakable: isbreakable)[ - // line 1: award title and location - #if award.url != none [ - *#link(award.url)[#award.title]* #h(1fr) *#award.location* \ - ] else [ - *#award.title* #h(1fr) *#award.location* \ - ] - // line 2: issuer and date - Issued by #text(style: "italic")[#award.issuer] #h(1fr) #date \ - // summary or description - #if award.highlights != none { - for hi in award.highlights [ - - #eval(hi, mode: "markup") - ] - } else {} + if info.awards != none { + block[ + == Honors & Awards + #for award in info.awards { + // parse ISO date strings into datetime objects + let date = utils.strpdate(lang, award.date) + // create a block layout for each award entry + block(width: 100%, breakable: isbreakable)[ + // line 1: award title and location + #if award.url != none [ + *#link(award.url)[#award.title]* #h(1fr) *#award.location* \ + ] else [ + *#award.title* #h(1fr) *#award.location* \ + ] + // line 2: issuer and date + Issued by #text(style: "italic")[#award.issuer] #h(1fr) #date \ + // summary or description + #if award.highlights != none { + for hi in award.highlights [ + - #eval(hi, mode: "markup") ] - } - ]} + } else {} + ] + } + ] + } } #let cvcertificates(lang, info, isbreakable: true) = { - if info.certificates != none {block[ - == Licenses & Certifications + if info.certificates != none { + block[ + == Licenses & Certifications - #for cert in info.certificates { - // parse ISO date strings into datetime objects - let date = utils.strpdate(lang, cert.date) - // create a block layout for each certificate entry - block(width: 100%, breakable: isbreakable)[ - // line 1: certificate name - #if cert.url != none [ - *#link(cert.url)[#cert.name]* \ - ] else [ - *#cert.name* \ - ] - // line 2: issuer and date - Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \ - ] - } - ]} + #for cert in info.certificates { + // parse ISO date strings into datetime objects + let date = utils.strpdate(lang, cert.date) + // create a block layout for each certificate entry + block(width: 100%, breakable: isbreakable)[ + // line 1: certificate name + #if cert.url != none [ + *#link(cert.url)[#cert.name]* \ + ] else [ + *#cert.name* \ + ] + // line 2: issuer and date + Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \ + ] + } + ] + } } #let cvpublications(lang, info, isbreakable: true) = { - if info.publications != none {block[ - == Research & Publications - #for pub in info.publications { - // parse ISO date strings into datetime objects - let date = utils.strpdate(lang, pub.releaseDate) - // create a block layout for each publication entry - block(width: 100%, breakable: isbreakable)[ - // line 1: publication title - #if pub.url != none [ - *#link(pub.url)[#pub.name]* \ - ] else [ - *#pub.name* \ - ] - // line 2: publisher and date - Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \ - ] - } - ]} + if info.publications != none { + block[ + == Research & Publications + #for pub in info.publications { + // parse ISO date strings into datetime objects + let date = utils.strpdate(lang, pub.releaseDate) + // create a block layout for each publication entry + block(width: 100%, breakable: isbreakable)[ + // line 1: publication title + #if pub.url != none [ + *#link(pub.url)[#pub.name]* \ + ] else [ + *#pub.name* \ + ] + // line 2: publisher and date + Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \ + ] + } + ] + } +} + +#let cvlanguages(lang, info, isbreakable: true) = { + block(breakable: isbreakable)[ + == #info.languages.title + + #for lang in info.languages.content { + [- *#lang.title*#text(weight: "light")[: #lang.content]] + } + ] } #let cvskills(lang, info, isbreakable: true) = { - block(breakable: isbreakable)[ - == #info.skills.title + block( + breakable: isbreakable, + )[ + == #info.skills.title - #for skill in info.skills.content { - [- *#skill.title*] - } - ] + #for skill in info.skills.content { + let skillContent = skill.content.sorted(key: x => { + if type(x) == dictionary { + x.keys().first() + } else { x } + }).map( + x => { + if type(x) == dictionary { + [#x.keys().first() (#text(style: "italic")[#x.values().first().sorted().join(", ")])] + } else { + [#x] + } + }, + ).join(", ") + + [- *#skill.title*#text(weight: "light")[: #skillContent]] + } + ] } #let cvreferences(info, isbreakable: true) = { - if info.references != none {block[ - == References - #for ref in info.references { - block(width: 100%, breakable: isbreakable)[ - #if ref.url != none [ - - *#link(ref.url)[#ref.name]*: "#ref.reference" - ] else [ - - *#ref.name*: "#ref.reference" - ] - ] - } - ]} else {} + if info.references != none { + block[ + == References + #for ref in info.references { + block(width: 100%, breakable: isbreakable)[ + #if ref.url != none [ + - *#link(ref.url)[#ref.name]*: "#ref.reference" + ] else [ + - *#ref.name*: "#ref.reference" + ] + ] + } + ] + } else {} } #let endnote() = { - place( - bottom + right, - block[ - #set text(size: 5pt, font: "Consolas", fill: silver) - Félix Desmaretz #datetime.today().display("[year]-[month]-[day]") - ] - ) + place(bottom + right, block[ + #set text(size: 5pt, font: "Consolas", fill: silver) + Félix Desmaretz #datetime.today().display("[year]-[month]-[day]") + ]) } \ No newline at end of file diff --git a/main.typ b/main.typ index 6ba05d4..ba3d0f6 100644 --- a/main.typ +++ b/main.typ @@ -1,48 +1,51 @@ #import "cv/cv.typ": * +#import "cv/utils.typ" -#let language = "en" +#let language = "fr" -#let cvdata = ( +#let cvdata = utils.filterLanguage(language, ( personal: yaml(("data/", "en", "/personal.yaml").join()), experience: yaml(("data/", "en", "/experience.yaml").join()), education: yaml(("data/", "en", "/education.yaml").join()), - skills: yaml(("data/", "en", "/skills.yaml").join()) -) + skills: yaml(("data/", "en", "/skills.yaml").join()), + languages: yaml("data/en/languages.yaml"), +)) #let uservars = ( - headingfont: "Roboto", - bodyfont: "Roboto", - fontsize: 10pt, // 10pt, 11pt, 12pt - linespacing: 6pt, - showAddress: true, // true/false show address in contact info - showNumber: true, // true/false show phone number in contact info - headingsmallcaps: false + headingfont: "Roboto", + bodyfont: "Roboto", + fontsize: 10pt, // 10pt, 11pt, 12pt + linespacing: 6pt, + showAddress: true, // true/false show address in contact info + showNumber: true, // true/false show phone number in contact info + headingsmallcaps: false, ) #let customrules(doc) = { - // add custom document style rules here - set page( - paper: "a4", // a4, us-letter - // numbering: "1 / 1", - number-align: center, // left, center, right - margin: 1.25cm, // 1.25cm, 1.87cm, 2.5cm - ) + // add custom document style rules here + set page( + paper: "a4", // a4, us-letter + // numbering: "1 / 1", + number-align: center, // left, center, right + margin: 1.25cm, // 1.25cm, 1.87cm, 2.5cm + ) - doc + doc } #let cvinit(doc) = { - doc = setrules(uservars, doc) - doc = showrules(uservars, doc) - doc = customrules(doc) + doc = setrules(uservars, doc) + doc = showrules(uservars, doc) + doc = customrules(doc) - doc + doc } #show: doc => cvinit(doc) -#cvheading(cvdata, uservars) +#cvheading(language, cvdata, uservars) #cvwork(language, cvdata) -// #cveducation(cvdata) -// #cvskills(cvdata) +#cveducation(language, cvdata) +#cvlanguages(language, cvdata) +#cvskills(language, cvdata) #endnote() \ No newline at end of file